<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.1.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/themes/green/pace-theme-minimal.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/pace.min.js" integrity="sha256-gqd7YTjg/BtfqWSwsJOvndl0Bxc8gFImLEkXQT8+qj0=" crossorigin="anonymous"></script>

<script class="next-config" data-name="main" type="application/json">{"hostname":"liukairui.me","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.10.1","exturl":false,"sidebar":{"position":"left","display":"hide","padding":18,"offset":12},"copycode":true,"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":true,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":false,"nav":null,"activeClass":"valine"},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="包含了前端主要构建工具,主讲:尚硅谷{&#39;张晓飞&#39;,&#39;熊键&#39;},视频来自B站:{&#39;BV18s411E7gQ&#39;, &#39;BV18s411E7T5&#39;, &#39;BV1e7411j7T5&#39;}">
<meta property="og:type" content="article">
<meta property="og:title" content="前端构建工具Grunt&amp;Gulp&amp;webpack笔记">
<meta property="og:url" content="http://liukairui.me/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/">
<meta property="og:site_name" content="LiuKairui Website">
<meta property="og:description" content="包含了前端主要构建工具,主讲:尚硅谷{&#39;张晓飞&#39;,&#39;熊键&#39;},视频来自B站:{&#39;BV18s411E7gQ&#39;, &#39;BV18s411E7T5&#39;, &#39;BV1e7411j7T5&#39;}">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-09-29T17:00:00.000Z">
<meta property="article:modified_time" content="2021-10-18T06:44:13.569Z">
<meta property="article:author" content="Liu Kairui">
<meta property="article:tag" content="前端">
<meta property="article:tag" content="笔记">
<meta property="article:tag" content="构建工具">
<meta property="article:tag" content="Grunt">
<meta property="article:tag" content="Gulp">
<meta property="article:tag" content="webpack">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="http://liukairui.me/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"http://liukairui.me/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/","path":"article/前端构建工具Grunt+Gulp+webpack/","title":"前端构建工具Grunt&Gulp&webpack笔记"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>前端构建工具Grunt&Gulp&webpack笔记 | LiuKairui Website</title>
  

  <script src="/js/third-party/analytics/baidu-analytics.js"></script>
  <script async src="https://hm.baidu.com/hm.js?ea07bceb8f5fa721da2ebf01833faa32"></script>



<div class="nindexBK">
<div class="nindexBKC"></div>
<div class="nindex">
  <h1>Hey👋</h1>
  <p style="font-weight: 500; font-size: 2.2em">欢迎访问Liu Kairui的个人站.</p>
  <p>
      我是一个来自重庆的在校大学生, 偏爱于前端技术<!--与OS设计-->, 偶尔使用 JS / Go 进行轻量项目开发, 欢迎访问我的
      <a href="https://github.com/KairuiLiu" target="_blank"><i class="fab fa-github-alt"></i> GitHub</a> .
  </p>
  <p>
      这个网站主要用来存储学习 / 瞎搞的笔记, 同时提供了邮件、图床等服务. 对于一些自认为有趣的<a href="javascript:;" id="myProj">项目</a>, 我也会将项目介绍, 文档, 甚至是设计指南发布在这里.
  </p>
  <ul>
    <li><p><a href="/artrank/" target="_blank">ArtRank</a>: 基于Node.JS的PageRank文献管理推荐系统</p></li>
    <li><p><a href="/gooj/" target="_blank">GoOJ</a>: 基于Golang的高校在线评测系统</p></li>
    <li><p><a href="/projects/" target="_blank">更多 <i class="fas fa-angle-right"></i></a></p></li>

  </ul>
  <p>
      可以在这些平台找到我: 
      <a href="https://www.zhihu.com/people/liu-kai-rui-18" target="_blank">知乎</a>,
      <a href="https://space.bilibili.com/33238144" target="_blank">bilibili</a>
      和
      <a href="https://www.coolapk.com/u/805314?from=qr" target="_blank">酷安</a>.
  </p>

  <p>
      下滑即可进入博客 <i class="fas fa-arrow-down"></i>
  </p>
</div>
</div>  

 
<script>
  var OriginTitile = document.title;
  var titleTime;
  document.addEventListener("visibilitychange", function() {
    if (document.hidden) {
      document.title = "谢谢离开 | " + OriginTitile;
      clearTimeout(titleTime);
    } else {
      document.title = "欢迎归来 | " + OriginTitile;
      titleTime = setTimeout(function() {
        document.title = OriginTitile;
      }, 2000);
    }
  });
</script>


<script>
  function checkIndex(){
    let nindexItems = [[".nindexBK","display","block","none"],[".headband","display","none","block"],["div.toggle.sidebar-toggle","visibility","hidden","visible"]]; // ,["button.darkmode-toggle","visibility","hidden","visible"]];
    let isIndex = new RegExp("^(\/){0,1}(index){0,1}(\.html){0,1}(/)*$").test(location.pathname);
    let backCanvas = document.querySelector(".nindexBK");
    nindexItems.dispShift = function (stat){this.forEach((e) => {try{document.querySelector(e[0]).style[e[1]]=e[2+stat];}catch{}})}
    if(isIndex){
      nindexItems.dispShift(0);
      window.onscroll=function(){
        if(document.documentElement.scrollTop>backCanvas.offsetHeight*1.05){
          nindexItems.dispShift(1);window.onscroll=null;
        }
      }
      document.querySelector("#myProj").onclick=()=>{
        let projlist = document.querySelector(".nindex>ul");
        projlist.className.indexOf("ulactive")==-1?projlist.classList.add("ulactive"):projlist.classList.remove("ulactive")
      }
    }else nindexItems.dispShift(1);
  }
  checkIndex();
</script>

<!--<script src="https://sdk.jinrishici.com/v2/browser/jinrishici.js" charset="utf-8"></script>-->

  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
<link rel="alternate" href="/atom.xml" title="LiuKairui Website" type="application/atom+xml">
<style>.darkmode--activated{--body-bg-color:#282828;--content-bg-color:#333;--card-bg-color:#555;--text-color:#ccc;--blockquote-color:#bbb;--link-color:#ccc;--link-hover-color:#eee;--brand-color:#ddd;--brand-hover-color:#ddd;--table-row-odd-bg-color:#282828;--table-row-hover-bg-color:#363636;--menu-item-bg-color:#555;--btn-default-bg:#222;--btn-default-color:#ccc;--btn-default-border-color:#555;--btn-default-hover-bg:#666;--btn-default-hover-color:#ccc;--btn-default-hover-border-color:#666;--highlight-background:#282b2e;--highlight-foreground:#a9b7c6;--highlight-gutter-background:#34393d;--highlight-gutter-foreground:#9ca9b6}.darkmode--activated img{opacity:.75}.darkmode--activated img:hover{opacity:.9}.darkmode--activated code{color:#69dbdc;background:0 0}button.darkmode-toggle{z-index:9999}.darkmode-ignore,img{display:flex!important}</style></head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">LiuKairui Website</p>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">要有信仰</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu">
        <li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li>
        <li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li>
        <li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fas fa-hashtag fa-fw"></i>标签</a></li>
        <li class="menu-item menu-item-收藏夹"><a href="/favorites/" rel="section"><i class="fab fa-gratipay fa-fw"></i>收藏夹</a></li>
        <li class="menu-item menu-item-留言板"><a href="/messageBoard/" rel="section"><i class="fab fa-facebook-messenger fa-fw"></i>留言板</a></li>
        <li class="menu-item menu-item-项目"><a href="/projects/" rel="section"><i class="fa fa-satellite fa-fw"></i>项目</a></li>
        <li class="menu-item menu-item-图床"><a href="http://img.liukairui.me/" rel="noopener" target="_blank"><i class="fa fa-bed fa-fw"></i>图床</a></li>
        <li class="menu-item menu-item-云ide"><a href="http://vsc.liukairui.me/" rel="noopener" target="_blank"><i class="fas fa-code fa-fw"></i>云IDE</a></li>
        <li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a></li>
        <li class="menu-item menu-item-邮箱"><a href="http://mail.liukairui.me/mail" rel="noopener" target="_blank"><i class="fas fa-envelope-open-text fa-fw"></i>邮箱</a></li>
        <li class="menu-item menu-item-rss"><a href="/atom.xml" rel="section"><i class="fa fa-rss fa-fw"></i>RSS</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#grunt%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA"><span class="nav-number">1.</span> <span class="nav-text">Grunt项目构建</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%A6%82%E8%BF%B0"><span class="nav-number">1.1.</span> <span class="nav-text">概述</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%88%E5%B9%B6js-concat%E6%8F%92%E4%BB%B6"><span class="nav-number">1.2.</span> <span class="nav-text">合并JS-concat插件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8E%8B%E7%BC%A9js-uglify"><span class="nav-number">1.3.</span> <span class="nav-text">压缩JS-uglify</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AF%AD%E6%B3%95%E6%A3%80%E6%9F%A5-jshint"><span class="nav-number">1.4.</span> <span class="nav-text">语法检查-jshint</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%88%E5%B9%B6%E5%8E%8B%E7%BC%A9css-cssmin"><span class="nav-number">1.5.</span> <span class="nav-text">合并压缩CSS-cssmin</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%87%AA%E5%8A%A8%E5%8C%96%E6%9E%84%E5%BB%BA%E6%8F%92%E4%BB%B6-watch"><span class="nav-number">1.6.</span> <span class="nav-text">自动化构建插件-watch</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%B3%E4%BA%8Ees6"><span class="nav-number">1.7.</span> <span class="nav-text">关于ES6</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#gulp%E9%A1%B9%E7%9B%AE%E6%9E%84%E5%BB%BA"><span class="nav-number">2.</span> <span class="nav-text">Gulp项目构建</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%A6%82%E8%BF%B0-1"><span class="nav-number">2.1.</span> <span class="nav-text">概述</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%90%88%E5%B9%B6%E5%8E%8B%E7%BC%A9js%E6%96%87%E4%BB%B6-concatuglifyrename"><span class="nav-number">2.2.</span> <span class="nav-text">合并压缩JS文件-concat&#x2F;uglify&#x2F;rename</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BD%AC%E8%AF%91less%E5%90%88%E5%B9%B6%E5%8E%8B%E7%BC%A9css%E6%96%87%E4%BB%B6-less%E4%B8%8Eclean-css"><span class="nav-number">2.3.</span> <span class="nav-text">转译Less合并压缩CSS文件-less与clean-css</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8E%8B%E7%BC%A9html%E6%96%87%E4%BB%B6-thmlmin"><span class="nav-number">2.4.</span> <span class="nav-text">压缩HTML文件-thmlmin</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8D%8A%E8%87%AA%E5%8A%A8%E5%8C%96%E6%9E%84%E5%BB%BA-livereload"><span class="nav-number">2.5.</span> <span class="nav-text">半自动化构建-livereload</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%A8%E8%87%AA%E5%8A%A8%E5%8C%96%E6%9E%84%E5%BB%BA%E5%AE%9E%E6%97%B6%E5%88%B7%E6%96%B0%E9%A1%B5%E9%9D%A2-connect%E4%B8%8Eopen"><span class="nav-number">2.6.</span> <span class="nav-text">全自动化构建(实时刷新页面)-connect与open</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%87%AA%E5%8A%A8%E5%BC%95%E5%85%A5gulp%E6%8F%92%E4%BB%B6-load-plugins"><span class="nav-number">2.7.</span> <span class="nav-text">自动引入gulp插件-load-plugins</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#webpack"><span class="nav-number">3.</span> <span class="nav-text">webpack</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%80%E4%BB%8B"><span class="nav-number">3.1.</span> <span class="nav-text">简介</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#webpack%E7%9A%84%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5"><span class="nav-number">3.1.1.</span> <span class="nav-text">webpack的核心概念</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="nav-number">3.2.</span> <span class="nav-text">基本使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE"><span class="nav-number">3.3.</span> <span class="nav-text">开发环境配置</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#webpack%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="nav-number">3.3.1.</span> <span class="nav-text">webpack配置文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%93%E5%8C%85cssless"><span class="nav-number">3.3.2.</span> <span class="nav-text">打包css&#x2F;less</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%93%E5%8C%85html"><span class="nav-number">3.3.3.</span> <span class="nav-text">打包html</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%93%E5%8C%85img"><span class="nav-number">3.3.4.</span> <span class="nav-text">打包img</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%93%E5%8C%85%E5%85%B6%E4%BB%96%E8%B5%84%E6%BA%90"><span class="nav-number">3.3.5.</span> <span class="nav-text">打包其他资源</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#devserver"><span class="nav-number">3.3.6.</span> <span class="nav-text">devserver</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE-1"><span class="nav-number">3.3.7.</span> <span class="nav-text">开发环境配置</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE"><span class="nav-number">3.4.</span> <span class="nav-text">生产环境配置</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%8F%90%E5%8F%96css%E4%B8%BA%E5%8D%95%E7%8B%AC%E6%96%87%E4%BB%B6"><span class="nav-number">3.4.1.</span> <span class="nav-text">提取CSS为单独文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#css%E5%85%BC%E5%AE%B9%E6%80%A7%E5%A4%84%E7%90%86"><span class="nav-number">3.4.2.</span> <span class="nav-text">CSS兼容性处理</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8E%8B%E7%BC%A9css"><span class="nav-number">3.4.3.</span> <span class="nav-text">压缩CSS</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#es%E8%AF%AD%E6%B3%95%E6%A3%80%E6%9F%A5"><span class="nav-number">3.4.4.</span> <span class="nav-text">ES语法检查</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#js%E5%85%BC%E5%AE%B9%E6%80%A7"><span class="nav-number">3.4.5.</span> <span class="nav-text">JS兼容性</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#js%E5%8E%8B%E7%BC%A9"><span class="nav-number">3.4.6.</span> <span class="nav-text">JS压缩</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#html%E5%8E%8B%E7%BC%A9"><span class="nav-number">3.4.7.</span> <span class="nav-text">html压缩</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE-1"><span class="nav-number">3.4.8.</span> <span class="nav-text">生产环境配置</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#webpack%E9%85%8D%E7%BD%AE%E4%BC%98%E5%8C%96"><span class="nav-number">3.5.</span> <span class="nav-text">webpack配置优化</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E4%BC%98%E5%8C%96"><span class="nav-number">3.6.</span> <span class="nav-text">开发环境配置优化</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%A8%A1%E5%9D%97%E7%83%AD%E6%9B%BF%E6%8D%A2hmr"><span class="nav-number">3.6.1.</span> <span class="nav-text">模块热替换HMR</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#sourcemap"><span class="nav-number">3.6.2.</span> <span class="nav-text">SourceMap</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE%E4%BC%98%E5%8C%96"><span class="nav-number">3.7.</span> <span class="nav-text">生产环境配置优化</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#oneof"><span class="nav-number">3.7.1.</span> <span class="nav-text">oneOf</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%BC%93%E5%AD%98%E7%9B%B8%E5%85%B3"><span class="nav-number">3.7.2.</span> <span class="nav-text">缓存相关</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#tree-shaking"><span class="nav-number">3.7.3.</span> <span class="nav-text">tree shaking</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#code-split"><span class="nav-number">3.7.4.</span> <span class="nav-text">code split</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#js%E6%96%87%E4%BB%B6%E7%9A%84%E6%87%92%E5%8A%A0%E8%BD%BD%E4%B8%8E%E9%A2%84%E5%8A%A0%E8%BD%BD"><span class="nav-number">3.7.5.</span> <span class="nav-text">JS文件的懒加载与预加载</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%B8%90%E8%BF%9B%E5%BC%8F%E7%BD%91%E9%A1%B5%E5%BA%94%E7%94%A8pwa%E7%A6%BB%E7%BA%BF%E5%8F%AF%E8%AE%BF%E9%97%AE"><span class="nav-number">3.7.6.</span> <span class="nav-text">渐进式网页应用PWA(离线可访问)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%A4%9A%E8%BF%9B%E7%A8%8B%E6%89%93%E5%8C%85"><span class="nav-number">3.7.7.</span> <span class="nav-text">多进程打包</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#externals%E7%A6%81%E6%AD%A2%E6%89%93%E5%8C%85"><span class="nav-number">3.7.8.</span> <span class="nav-text">externals禁止打包</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#ddl%E5%8A%A8%E6%80%81%E9%93%BE%E6%8E%A5%E5%BA%93"><span class="nav-number">3.7.9.</span> <span class="nav-text">ddl动态链接库</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E5%B1%9E%E6%80%A7%E8%AF%A6%E7%BB%86%E9%85%8D%E7%BD%AE"><span class="nav-number">3.8.</span> <span class="nav-text">基本属性详细配置</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#entry"><span class="nav-number">3.8.1.</span> <span class="nav-text">Entry</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#output"><span class="nav-number">3.8.2.</span> <span class="nav-text">output</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#module"><span class="nav-number">3.9.</span> <span class="nav-text">module</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#resolve"><span class="nav-number">3.10.</span> <span class="nav-text">resolve</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#devserver-1"><span class="nav-number">3.11.</span> <span class="nav-text">devServer</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#optimization"><span class="nav-number">3.12.</span> <span class="nav-text">optimization</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#webpack5%E7%9A%84%E5%8F%98%E5%8C%96"><span class="nav-number">3.13.</span> <span class="nav-text">webpack5的变化</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%87%AA%E5%8A%A8%E5%88%A0%E9%99%A4-node.js-polyfills"><span class="nav-number">3.13.1.</span> <span class="nav-text">自动删除 Node.js Polyfills</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#chunk-%E5%92%8C%E6%A8%A1%E5%9D%97-id"><span class="nav-number">3.13.2.</span> <span class="nav-text">Chunk 和模块 ID</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#chunk-id"><span class="nav-number">3.13.3.</span> <span class="nav-text">Chunk ID</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#tree-shaking-1"><span class="nav-number">3.13.4.</span> <span class="nav-text">Tree Shaking</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#output-1"><span class="nav-number">3.13.5.</span> <span class="nav-text">Output</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#splitchunk"><span class="nav-number">3.13.6.</span> <span class="nav-text">SplitChunk</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#caching"><span class="nav-number">3.13.7.</span> <span class="nav-text">Caching</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%9B%91%E8%A7%86%E8%BE%93%E5%87%BA%E6%96%87%E4%BB%B6"><span class="nav-number">3.13.8.</span> <span class="nav-text">监视输出文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%BB%98%E8%AE%A4%E5%80%BC"><span class="nav-number">3.13.9.</span> <span class="nav-text">默认值</span></a></li></ol></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Liu Kairui"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">Liu Kairui</p>
  <div class="site-description" itemprop="description">LiuKairui Persional Website</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">45</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">24</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">53</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author site-overview-item animated">
      <span class="links-of-author-item">
        <a href="https://github.com/KairuiLiu" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;KairuiLiu" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:tclkr@live.com" title="E-Mail → mailto:tclkr@live.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://qm.qq.com/cgi-bin/qm/qr?k=oaf3ToOlN17hr5sHV98bT8qxsNYGaw5L&noverify=0" title="QQ → https:&#x2F;&#x2F;qm.qq.com&#x2F;cgi-bin&#x2F;qm&#x2F;qr?k&#x3D;oaf3ToOlN17hr5sHV98bT8qxsNYGaw5L&amp;noverify&#x3D;0" rel="noopener" target="_blank"><i class="fab fa-qq fa-fw"></i>QQ</a>
      </span>
      <span class="links-of-author-item">
        <a href="/atom.xml" title="RSS → &#x2F;atom.xml"><i class="fa fa-rss fa-fw"></i>RSS</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://liukairui.blog.csdn.net/" title="CSDN → https:&#x2F;&#x2F;liukairui.blog.csdn.net" rel="noopener" target="_blank"><i class="fab fa-cuttlefish fa-fw"></i>CSDN</a>
      </span>
      <span class="links-of-author-item">
        <a href="http://liukairui.cc/" title="国内站点 → http:&#x2F;&#x2F;liukairui.cc" rel="noopener" target="_blank"><i class="fa fa-globe fa-fw"></i>国内站点</a>
      </span>
  </div>
  <div class="cc-license site-overview-item animated" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="https://cdnjs.cloudflare.com/ajax/libs/creativecommons-vocabulary/2020.11.3/assets/license_badges/small/by_nc_sa.svg" alt="Creative Commons"></a>
  </div>


  <div class="links-of-blogroll site-overview-item animated">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://paste.ubuntu.com/" title="https:&#x2F;&#x2F;paste.ubuntu.com&#x2F;" rel="noopener" target="_blank">Ubuntu Pastebin</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://send.firefox.com/" title="https:&#x2F;&#x2F;send.firefox.com&#x2F;" rel="noopener" target="_blank">Firefox Send</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://jkwzs.cn/" title="https:&#x2F;&#x2F;jkwzs.cn&#x2F;" rel="noopener" target="_blank">南花醉笔丶の个人博客</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://ywrby.cn/" title="https:&#x2F;&#x2F;ywrby.cn&#x2F;" rel="noopener" target="_blank">Ywrby个人博客</a>
        </li>
    </ul>
  </div>

        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://liukairui.me/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="Liu Kairui">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="LiuKairui Website">
      <meta itemprop="description" content="LiuKairui Persional Website">
    </span>
    
    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="前端构建工具Grunt&Gulp&webpack笔记 | LiuKairui Website">
      <meta itemprop="description" content="包含了前端主要构建工具,主讲:尚硅谷{'张晓飞','熊键'},视频来自B站:{'BV18s411E7gQ', 'BV18s411E7T5', 'BV1e7411j7T5'}">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          前端构建工具Grunt&Gulp&webpack笔记
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-09-30 01:00:00" itemprop="dateCreated datePublished" datetime="2021-09-30T01:00:00+08:00">2021-09-30</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%89%8D%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">前端</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%89%8D%E7%AB%AF/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/" itemprop="url" rel="index"><span itemprop="name">构建工具</span></a>
        </span>
    </span>

  
    <span id="/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/" class="post-meta-item leancloud_visitors" data-flag-title="前端构建工具Grunt&Gulp&webpack笔记" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="far fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
  
  <span class="post-meta-item">
    
    <span class="post-meta-item-icon">
      <i class="far fa-comment"></i>
    </span>
    <span class="post-meta-item-text">Valine：</span>
  
    <a title="valine" href="/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/" itemprop="commentCount"></span>
    </a>
  </span>
  
  

<script>
    CONFIG.hostname = location.hostname;
</script>
    <span class="post-meta-break"></span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>31k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>28 分钟</span>
    </span>
</div>

            <div class="post-description">包含了前端主要构建工具,主讲:尚硅谷{'张晓飞','熊键'},视频来自B站:{'BV18s411E7gQ', 'BV18s411E7T5', 'BV1e7411j7T5'}</div>
        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <h2 id="grunt项目构建">Grunt项目构建</h2>
<h3 id="概述">概述</h3>
<p>项目构建就是并编译, 合并, 压缩项目中的JS, SASS, LESS文件;
压缩HTML资源文件; JS语法检查</p>
<p><a target="_blank" rel="noopener" href="https://gruntjs.com/">Grunt</a>就是用来进行自动化项目构建的,
Grunt由一组插件组成, 围绕Grunt工作实现自动化, 常见的功能有</p>
<ul>
<li>合并JS/CSS</li>
<li>压缩JS/CSS</li>
<li>JS语法检查</li>
<li>LESS/SESS的预编译</li>
</ul>
<p><strong>目录结构</strong> <pre class="language-bash" data-language="bash"><code class="language-bash">├── build           // 生成构建文件所在文件夹
├── Gruntfile.js    // grunt配置文件, 首字母大写, 与.bablerc配置差不多
├── index.html
├── package.json
└── src             // 源码文件
    ├── css
    └── js</code></pre></p>
<p><strong>安装Grunt</strong> <pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">sudo</span> <span class="token function">npm</span> <span class="token function">install</span> grunt-cli -g
<span class="token function">npm</span> <span class="token function">install</span> grunt --include<span class="token operator">=</span>dev</code></pre></p>
<p><strong>Geuntrc.js配置</strong></p>
<p>使用js语法配置, 支持CommonJS规范, 配置方法 <pre class="language-js" data-language="js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">grunt</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token comment">// 初始化配置grunt任务</span>
    grunt<span class="token punctuation">.</span><span class="token function">initConfig</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>

    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// grunt执行的时候需要的任务插件(随便写了一个插件)</span>
    grunt<span class="token punctuation">.</span><span class="token function">loadNpmTasks</span><span class="token punctuation">(</span><span class="token string">'grunt-contrib-uglify'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// 注册Grunt的默认任务, 与执行任务的时候的依赖任务</span>
    grunt<span class="token punctuation">.</span><span class="token function">registerTask</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token string">'uglify'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p><strong>常用任务插件(先了解下)</strong></p>
<ul>
<li>grunt-contrib-concat——合并多个文件的代码到一个文件中</li>
<li>grunt-contrib-clean——清除文件(打包处理生成的)</li>
<li>grunt-contrib-uglify——压缩js文件</li>
<li>grunt-contrib-jshint——javascript语法错误检查；</li>
<li>grunt-contrib-cssmin——压缩/合并css文件</li>
<li>grunt-contrib-htmlmin——压缩html文件</li>
<li>grunt-contrib-imagemin——压缩图片文件(无损)</li>
<li>grunt-contrib-copy——复制文件、文件夹</li>
<li>grunt-contrib-requirejs——合并压缩requirejs管理的所有js模块文件</li>
<li>grunt-contrib-watch——实时监控文件变化、调用相应的任务重新执行</li>
</ul>
<h3 id="合并js-concat插件">合并JS-concat插件</h3>
<p>最好去官网找<a
target="_blank" rel="noopener" href="https://www.npmjs.com/package/grunt-contrib-concat">说明</a></p>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> grunt-contrib-concat --include<span class="token operator">=</span>dev</code></pre>
<p>引入包 <pre class="language-js" data-language="js"><code class="language-js">grunt<span class="token punctuation">.</span><span class="token function">loadNpmTasks</span><span class="token punctuation">(</span><span class="token string">'grunt-contrib-concat'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> 在using example中找到配置示例 <pre class="language-js" data-language="js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">grunt</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 初始化配置grunt任务</span>
    grunt<span class="token punctuation">.</span><span class="token function">initConfig</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
        <span class="token literal-property property">concat</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
            <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                <span class="token literal-property property">separator</span><span class="token operator">:</span> <span class="token string">';'</span><span class="token punctuation">,</span> <span class="token comment">// 链接符号</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
            <span class="token literal-property property">dist</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                <span class="token literal-property property">src</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'src/js/*.js'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// 合并哪些文件</span>
                <span class="token literal-property property">dest</span><span class="token operator">:</span> <span class="token string">'dist/built.js'</span><span class="token punctuation">,</span> <span class="token comment">// 输出目录</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// grunt执行的时候需要的任务插件</span>
    grunt<span class="token punctuation">.</span><span class="token function">loadNpmTasks</span><span class="token punctuation">(</span><span class="token string">'grunt-contrib-concat'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// 注册Grunt的默认任务, 与执行任务的时候的依赖任务</span>
    grunt<span class="token punctuation">.</span><span class="token function">registerTask</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'concat'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p>执行命令(当然, 我们注册了默认任务, 可以不写concat) <pre class="language-npm" data-language="npm"><code class="language-npm">grunt concat</code></pre></p>
<h3 id="压缩js-uglify">压缩JS-uglify</h3>
<pre class="language-js" data-language="js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">grunt</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 初始化配置grunt任务</span>
    grunt<span class="token punctuation">.</span><span class="token function">initConfig</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
        <span class="token literal-property property">concat</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
            <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                <span class="token literal-property property">separator</span><span class="token operator">:</span> <span class="token string">';'</span><span class="token punctuation">,</span> <span class="token comment">// 链接符号</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
            <span class="token literal-property property">dist</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                <span class="token literal-property property">src</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'src/js/*.js'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// 合并哪些文件</span>
                <span class="token literal-property property">dest</span><span class="token operator">:</span> <span class="token string">'dist/built.js'</span><span class="token punctuation">,</span> <span class="token comment">// 输出目录</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>

        <span class="token literal-property property">uglify</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
            <span class="token literal-property property">my_target</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                    <span class="token string-property property">'dist/output.min.js'</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'src/js/test1.js'</span><span class="token punctuation">]</span>
                <span class="token punctuation">&#125;</span>
            <span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// grunt执行的时候需要的任务插件</span>
    grunt<span class="token punctuation">.</span><span class="token function">loadNpmTasks</span><span class="token punctuation">(</span><span class="token string">'grunt-contrib-concat'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">+</span>
    grunt<span class="token punctuation">.</span><span class="token function">loadNpmTasks</span><span class="token punctuation">(</span><span class="token string">'grunt-contrib-uglify'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// 注册Grunt的默认任务, 与执行任务的时候的依赖任务</span>
    grunt<span class="token punctuation">.</span><span class="token function">registerTask</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'concat'</span><span class="token punctuation">,</span> <span class="token string">'uglify'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>        <span class="token comment">// 注意, 任务应该有序给出, Grunt执行任务是同步的</span>
<span class="token punctuation">&#125;</span></code></pre>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> grunt-contrib-uglify 
grunt uglify </code></pre>
<h3 id="语法检查-jshint">语法检查-jshint</h3>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> grunt-contrib-jshint -dev</code></pre>
<p>加载插件 <pre class="language-js" data-language="js"><code class="language-js">grunt<span class="token punctuation">.</span><span class="token function">loadNpmTasks</span><span class="token punctuation">(</span><span class="token string">'grunt-contrib-jshint'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> 注册到任务 <pre class="language-js" data-language="js"><code class="language-js">grunt<span class="token punctuation">.</span><span class="token function">registerTask</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'concat'</span><span class="token punctuation">,</span> <span class="token string">'uglify'</span><span class="token punctuation">,</span> <span class="token string">'jshint'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
在与<code>Gruntfile.js</code>同目录创建配置文件<code>.jshintrc</code>,
举例 <pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token string-property property">"curly"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"eqeqeq"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"eqnull"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"expr"</span> <span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"immed"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"newcap"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"noempty"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"noarg"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"regexp"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"browser"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"devel"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"node"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token string-property property">"boss"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
  
  <span class="token comment">//不能使用未定义的变量</span>
  <span class="token string-property property">"undef"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token comment">//语句后面必须有分号</span>
  <span class="token string-property property">"asi"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
  <span class="token comment">//预定义不检查的全局变量</span>
  <span class="token string-property property">"predef"</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token string">"define"</span><span class="token punctuation">,</span> <span class="token string">"BMap"</span><span class="token punctuation">,</span> <span class="token string">"angular"</span><span class="token punctuation">,</span> <span class="token string">"BMAP_STATUS_SUCCESS"</span><span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span></code></pre> 增加配置内容 <pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">jshint</span> <span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">jshintrc</span> <span class="token operator">:</span> <span class="token string">'.jshintrc'</span> <span class="token comment">//指定配置文件</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">build</span> <span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'Gruntfile.js'</span><span class="token punctuation">,</span> <span class="token string">'src/js/*.js'</span><span class="token punctuation">]</span> <span class="token comment">//指定检查的文件</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<h3 id="合并压缩css-cssmin">合并压缩CSS-cssmin</h3>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> grunt-contrib-cssmin -dev</code></pre>
<p>配置Gruntfile.js <pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">cssmin</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>                        <span class="token comment">// 保证结果准确</span>
    <span class="token literal-property property">shorthandCompacting</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>     <span class="token comment">// 快速压缩</span>
    <span class="token literal-property property">roundingPrecision</span><span class="token operator">:</span> <span class="token operator">-</span><span class="token number">1</span>           <span class="token comment">// 精度-1</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">build</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">files</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token string-property property">'build/css/output.min.css'</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'src/css/*.css'</span><span class="token punctuation">]</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre> 添加与注册插件: 略</p>
<h3 id="自动化构建插件-watch">自动化构建插件-watch</h3>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> grunt-contrib-watch -dev</code></pre>
<p><strong>配置任务</strong>: <pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">watch</span> <span class="token builtin class-name">:</span> <span class="token punctuation">&#123;</span>
    scripts <span class="token builtin class-name">:</span> <span class="token punctuation">&#123;</span>
        files <span class="token builtin class-name">:</span> <span class="token punctuation">[</span><span class="token string">'src/js/*.js'</span>, <span class="token string">'src/css/*.css'</span><span class="token punctuation">]</span>,           // 需要的文件
        tasks <span class="token builtin class-name">:</span> <span class="token punctuation">[</span><span class="token string">'concat'</span>, <span class="token string">'jshint'</span>, <span class="token string">'uglify'</span>, <span class="token string">'cssmin'</span><span class="token punctuation">]</span>,   // 执行队列
        options <span class="token builtin class-name">:</span> <span class="token punctuation">&#123;</span>spawn <span class="token builtin class-name">:</span> false<span class="token punctuation">&#125;</span>                           // 是否全量更新<span class="token punctuation">(</span>例如css修改, 是否重新编译js<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre> <strong>加载任务</strong>
<pre class="language-js" data-language="js"><code class="language-js">grunt<span class="token punctuation">.</span><span class="token function">loadNpmTasks</span><span class="token punctuation">(</span><span class="token string">'grunt-contrib-watch'</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> 注册任务: <pre class="language-js" data-language="js"><code class="language-js">grunt<span class="token punctuation">.</span><span class="token function">registerTask</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'concat'</span><span class="token punctuation">,</span> <span class="token string">'uglify'</span><span class="token punctuation">,</span> <span class="token string">'watch'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> 命令: <pre class="language-bash" data-language="bash"><code class="language-bash">grunt   //控制台提示watch已经开始监听, 修改保存后自动编译处理</code></pre> 或者</p>
<p>注册任务: <pre class="language-js" data-language="js"><code class="language-js">grunt<span class="token punctuation">.</span><span class="token function">registerTask</span><span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'concat'</span><span class="token punctuation">,</span> <span class="token string">'uglify'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
grunt<span class="token punctuation">.</span><span class="token function">registerTask</span><span class="token punctuation">(</span><span class="token string">'myWatch'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'default'</span><span class="token punctuation">,</span><span class="token string">'watch'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre> 命令: <pre class="language-bash" data-language="bash"><code class="language-bash">grunt myWatch</code></pre></p>
<h3 id="关于es6">关于ES6</h3>
<p>Grunt插件不支持ES6, 所以处理ES6代码时候应该先使用babel转换,
然后再Grunt</p>
<h2 id="gulp项目构建">Gulp项目构建</h2>
<h3 id="概述-1">概述</h3>
<p><a
target="_blank" rel="noopener" href="https://gulpjs.com/">Gulp</a>是与Grunt功能类似的更加高效的<strong>前端项目构建工具</strong>,
可以基于Node自动的完成代码的检查, 压缩, 合并, 监听, 测试等.
具有如下特点</p>
<ul>
<li>任务化: 所有的事件都有一个统一的接口,
不论做什么都要先去注册一个任务</li>
<li>基于流: 基于数据流, Gulp有自己的内存, 在调用Gulp的时候,
程序会将目标文件读入Gulp内存中, 然后通过IO输出数据</li>
<li>执行任务可以同步,也可以异步</li>
<li><strong>与Grunt一样不支持ES6,如需使用请提前Babel</strong></li>
</ul>
<p><strong>重要API</strong></p>
<ul>
<li><code>gulp.src(path)</code>: 根据路径读取源文件</li>
<li><code>gulp.dest(path)</code>: 根据路径输出文件</li>
<li><code>gulp.task(name[,deps],fn)</code>: 调取命令</li>
<li><code>gulp.wartch(glob[,opts],tasks)</code>或<code>gulp.wartch(glob[,opts,cb])</code>:
文件发生变动时修改</li>
</ul>
<p><strong>文件结构</strong> <pre class="language-none"><code class="language-none">├── dist
├── gulpfile.js
├── index.html
├── package.json
└── src
    ├── css
    ├── js
    └── less</code></pre></p>
<p><strong>全局与局部安装</strong> <pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> gulp -g
<span class="token function">npm</span> <span class="token function">install</span> gulp --include<span class="token operator">=</span>dev</code></pre></p>
<p><strong>gulpfile.js的配置</strong></p>
<ul>
<li>任务的创建
<ul>
<li>注册任务与默认任务<br />
任务有公开任务与是有任务, 公开任务中的default可以直接使用glup调用
<ul>
<li>公开任务（Public tasks） 从 gulpfile 中被导出（export），可以通过
gulp 命令直接调用。</li>
<li>私有任务（Private tasks） 被设计为在内部使用，通常作为 series() 或
parallel() 组合的组成部分。<br />
可以使用<code>tasks</code>创建任务, 私有任务无法直接被调用,
如果希望直接调用需要<code>exports</code>导出<br />
</li>
</ul></li>
<li>组合任务<br />
Gulp支持与Grunt类似的任务组合,
组合任务有<code>series(task1, task2...)</code> 和
<code>parallel(task1, task2...)</code>, 两者可以相互嵌套,
区别是<code>series</code>是同步的, <code>parallel</code>是异步的,
两者无限嵌套就实现了依赖处理, 例如: <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> series <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// `clean` 函数并未被导出（export），因此被认为是私有任务（private task）。</span>
<span class="token comment">// 它仍然可以被用在 `series()` 组合中。</span>
<span class="token keyword">function</span> <span class="token function">clean</span><span class="token punctuation">(</span><span class="token parameter">cb</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token comment">// body omitted</span>
<span class="token function">cb</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">// `build` 函数被导出（export）了，因此它是一个公开任务（public task），并且可以被 `gulp` 命令直接调用。</span>
<span class="token comment">// 它也仍然可以被用在 `series()` 组合中。</span>
<span class="token keyword">function</span> <span class="token function">build</span><span class="token punctuation">(</span><span class="token parameter">cb</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
<span class="token comment">// body omitted</span>
<span class="token function">cb</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

exports<span class="token punctuation">.</span>build <span class="token operator">=</span> build<span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>default <span class="token operator">=</span> <span class="token function">series</span><span class="token punctuation">(</span>clean<span class="token punctuation">,</span> build<span class="token punctuation">)</span><span class="token punctuation">;</span>     <span class="token comment">// 组合任务输出</span></code></pre></li>
</ul></li>
<li>常见插件
<ul>
<li>gulp-concat : 合并文件(js/css)</li>
<li>gulp-uglify : 压缩js文件</li>
<li>gulp-rename : 文件重命名</li>
<li>gulp-less : 编译less</li>
<li>gulp-clean-css : 压缩css</li>
<li>gulp-livereload : 实时自动编译刷新</li>
</ul></li>
</ul>
<h3
id="合并压缩js文件-concatuglifyrename">合并压缩JS文件-concat/uglify/rename</h3>
<p>安装(注意这里需要对文件进行管道等操作所以要多下载包) <pre class="language-none"><code class="language-none">npm install gulp-concat gulp-uglify gulp-rename -dev</code></pre>
配置文件 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> gulp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>             <span class="token comment">// 引入</span>
<span class="token keyword">var</span> concat <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-concat'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> uglify <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-uglify'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
<span class="token keyword">var</span> rename <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-rename'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 

<span class="token keyword">function</span> <span class="token function">ChuLiJS</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                  <span class="token comment">// ! 虽然没有return也可以执行, 但是"玄学上"有return的话执行结束才会释放GULP空间</span>
  <span class="token keyword">return</span> gulp<span class="token punctuation">.</span><span class="token function">src</span><span class="token punctuation">(</span><span class="token string">'./src/js/*.js'</span><span class="token punctuation">)</span>      <span class="token comment">// 源文件 =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token string">'all.js'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>             <span class="token comment">// 合并成 =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>gulp<span class="token punctuation">.</span><span class="token function">dest</span><span class="token punctuation">(</span><span class="token string">'./dist/'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>         <span class="token comment">// 输出到 =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">uglify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>                     <span class="token comment">// 压缩文件 =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">rename</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span><span class="token literal-property property">suffix</span><span class="token operator">:</span> <span class="token string">'.min'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>     <span class="token comment">// 重命名(仅修改后缀, 不动扩展名) =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>gulp<span class="token punctuation">.</span><span class="token function">dest</span><span class="token punctuation">(</span><span class="token string">'./dist/'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>         <span class="token comment">// 输出到</span>
<span class="token punctuation">&#125;</span>

exports<span class="token punctuation">.</span>ChuLiJS <span class="token operator">=</span> ChuLiJS<span class="token punctuation">;</span></code></pre></p>
<h3
id="转译less合并压缩css文件-less与clean-css">转译Less合并压缩CSS文件-less与clean-css</h3>
<p>安装 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install gulp-less gulp-clean-css -dev</code></pre> 配置文件 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> gulp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>             <span class="token comment">// 引入</span>
<span class="token keyword">var</span> concat <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-concat'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> less <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-less'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> cleanCss <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-clean-css'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>


<span class="token keyword">function</span> <span class="token function">ChuLiLess</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> gulp<span class="token punctuation">.</span><span class="token function">src</span><span class="token punctuation">(</span><span class="token string">'./src/less/*.less'</span><span class="token punctuation">)</span>    <span class="token comment">// 源文件 =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">less</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>                         <span class="token comment">// 编译成 =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>gulp<span class="token punctuation">.</span><span class="token function">dest</span><span class="token punctuation">(</span><span class="token string">'./src/css/'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>        <span class="token comment">// 输出到</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">ChuLiCss</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> gulp<span class="token punctuation">.</span><span class="token function">src</span><span class="token punctuation">(</span><span class="token string">'./src/css/*.css'</span><span class="token punctuation">)</span>         <span class="token comment">// 源文件 =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">concat</span><span class="token punctuation">(</span><span class="token string">'build.css'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>               <span class="token comment">// 合并成 =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">cleanCss</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span><span class="token literal-property property">compatibility</span><span class="token operator">:</span> <span class="token string">'ie8'</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>  <span class="token comment">// 压缩并兼容IE8 =管道=></span>
    <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>gulp<span class="token punctuation">.</span><span class="token function">dest</span><span class="token punctuation">(</span><span class="token string">'./dist/css/'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>          <span class="token comment">// 输出到</span>

<span class="token punctuation">&#125;</span>

exports<span class="token punctuation">.</span>ChuLiStyle <span class="token operator">=</span> gulp<span class="token punctuation">.</span><span class="token function">series</span><span class="token punctuation">(</span>ChuLiLess<span class="token punctuation">,</span>ChuLiCss<span class="token punctuation">)</span><span class="token punctuation">;</span>   <span class="token comment">// 必须同步撒</span></code></pre></p>
<h3 id="压缩html文件-thmlmin">压缩HTML文件-thmlmin</h3>
<p>安装文件 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install gulp-htmlmin -dev</code></pre> 配置举例 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">var</span> gulp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>             <span class="token comment">// 引入</span>
<span class="token keyword">var</span> htmlMin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-htmlmin'</span><span class="token punctuation">)</span>

<span class="token keyword">function</span> <span class="token function">ChuLiHtml</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> gulp<span class="token punctuation">.</span><span class="token function">src</span><span class="token punctuation">(</span><span class="token string">'./index.html'</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">htmlMin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span><span class="token literal-property property">collapseWhitespace</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>   <span class="token comment">// 删除空格</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>gulp<span class="token punctuation">.</span><span class="token function">dest</span><span class="token punctuation">(</span><span class="token string">'./dist/'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>                <span class="token comment">// 注意, 此时的引用文件相对路径错了, 所以注意写代码的时候路径地址</span>
<span class="token punctuation">&#125;</span>

exports<span class="token punctuation">.</span>ChuLiHtml <span class="token operator">=</span> ChuLiHtml<span class="token punctuation">;</span></code></pre></p>
<h3 id="半自动化构建-livereload">半自动化构建-livereload</h3>
<p>安装文件 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install gulp-livereload -dev</code></pre> 配置举例(监控HTML) <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> series <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> gulp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> htmlMin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-htmlmin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> liveReload <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-livereload'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>


<span class="token keyword">function</span> <span class="token function">ChuLiHtml</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> gulp<span class="token punctuation">.</span><span class="token function">src</span><span class="token punctuation">(</span><span class="token string">'./index.html'</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">htmlMin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span><span class="token literal-property property">collapseWhitespace</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>   <span class="token comment">// 删除空格</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>gulp<span class="token punctuation">.</span><span class="token function">dest</span><span class="token punctuation">(</span><span class="token string">'./dist/'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">liveReload</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>         <span class="token comment">// [选]也可以添加这么一行手动调用实时刷新</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">ChuLiLive</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token comment">// 开启监听</span>
  liveReload<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  gulp<span class="token punctuation">.</span><span class="token function">watch</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'./index.html'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token function">series</span><span class="token punctuation">(</span><span class="token string">'ChuLiHtml'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// gulp.watch(['./src/less/*.less', './src/css/*.css'], series('ChuLiLess', 'ChuLiCss'))    // 支持注册多个模块</span>
<span class="token punctuation">&#125;</span>

exports<span class="token punctuation">.</span>ChuLiHtml <span class="token operator">=</span> ChuLiHtml<span class="token punctuation">;</span>    <span class="token comment">// 需要开放</span>
exports<span class="token punctuation">.</span>default <span class="token operator">=</span> ChuLiLive<span class="token punctuation">;</span>  </code></pre></p>
<h3
id="全自动化构建实时刷新页面-connect与open">全自动化构建(实时刷新页面)-connect与open</h3>
<p>安装 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install gulp-connect open -dev</code></pre> 配置举例(监控HTML) <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> series <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> gulp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> htmlMin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-htmlmin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> connect <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-connect'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> open <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'open'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">ChuLiHtml</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> gulp<span class="token punctuation">.</span><span class="token function">src</span><span class="token punctuation">(</span><span class="token string">'./index.html'</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">htmlMin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span><span class="token literal-property property">collapseWhitespace</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>   <span class="token comment">// 删除空格</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>gulp<span class="token punctuation">.</span><span class="token function">dest</span><span class="token punctuation">(</span><span class="token string">'./dist/'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>connect<span class="token punctuation">.</span><span class="token function">reload</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>         <span class="token comment">// ! 添加这么一行手动调用实时刷新</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">server</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token comment">// connect 提供了一个微型服务器让浏览器访问, 并刷新</span>
  <span class="token comment">// 根目录, 实时刷新?, 端口</span>
  connect<span class="token punctuation">.</span><span class="token function">server</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">root</span><span class="token operator">:</span> <span class="token string">'./dist'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">livereload</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token literal-property property">port</span><span class="token operator">:</span> <span class="token number">5000</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token function">open</span><span class="token punctuation">(</span><span class="token string">"http://localhost:5000/"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token comment">// 打开页面</span>

  gulp<span class="token punctuation">.</span><span class="token function">watch</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'./index.html'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token function">series</span><span class="token punctuation">(</span><span class="token string">'ChuLiHtml'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// gulp.watch(['./src/less/*.less', './src/css/*.css'], series('ChuLiLess', 'ChuLiCss'))    // 支持注册多个模块</span>
<span class="token punctuation">&#125;</span>

exports<span class="token punctuation">.</span>ChuLiHtml <span class="token operator">=</span> ChuLiHtml<span class="token punctuation">;</span>    <span class="token comment">// 需要开放</span>
exports<span class="token punctuation">.</span>default <span class="token operator">=</span> server<span class="token punctuation">;</span>  </code></pre></p>
<h3
id="自动引入gulp插件-load-plugins">自动引入gulp插件-load-plugins</h3>
<p>原来的gulpfile.js文件 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> series <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> gulp <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> htmlmin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'gulp-htmlmin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">ChuLiHtml</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> gulp<span class="token punctuation">.</span><span class="token function">src</span><span class="token punctuation">(</span><span class="token string">'./index.html'</span><span class="token punctuation">)</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span><span class="token function">htmlmin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span><span class="token literal-property property">collapseWhitespace</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">)</span>   <span class="token comment">// 删除空格</span>
      <span class="token punctuation">.</span><span class="token function">pipe</span><span class="token punctuation">(</span>gulp<span class="token punctuation">.</span><span class="token function">dest</span><span class="token punctuation">(</span><span class="token string">'./dist/'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span>

exports<span class="token punctuation">.</span>ChuLiHtml <span class="token operator">=</span> ChuLiHtml<span class="token punctuation">;</span>    <span class="token comment">// 需要开放</span>
exports<span class="token punctuation">.</span>default <span class="token operator">=</span> server<span class="token punctuation">;</span>  </code></pre> 为了减少多次require,
可以使用插件gulp-load-plugins</p>
<p>安装 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install gulp-load-plugins -dev</code></pre> 使用 <pre class="language-diff" data-language="diff"><code class="language-diff">var gulp = require('gulp');
<span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> var $ = require('gulp-load-plugins')();       // 引入的插件是个方法，必须记住调用。
</span></span><span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line"> var htmlmin = require('gulp-htmlmin');</span></span></code></pre>
在使用的时候需要将<code>方法</code>改为<code>$.方法</code>
<pre class="language-diff" data-language="diff"><code class="language-diff">function ChuLiHtml()&#123;
<span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> return gulp.src('./index.html')
</span></span><span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line">      .pipe(htmlmin(&#123;collapseWhitespace:true&#125;))   // 删除空格
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line">      .pipe($.htmlmin(&#123;collapseWhitespace:true&#125;))   // 删除空格
</span></span><span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line">     .pipe(gulp.dest('./dist/'))
</span></span>&#125;</code></pre> 对于插件名后缀有<code>-</code>的采用驼峰命名,
例如<code>gulp-load-clean-css</code>改为<code>cleanCss</code></p>
<h2 id="webpack">webpack</h2>
<h3 id="简介">简介</h3>
<p>webpack是一种前端资源构建工具, 也是一个静态模块打包器</p>
<ul>
<li>构建工具: 我们在写网页的时候需要合并压缩JS, 编译less,
在之前我们一般是单独维护每一个小工具最后实现所有功能,
现在可以使用构建工具整合所有的操作</li>
<li>静态模块打包器: 文件在编写的时候可能会应用其他的模块,
文件类型(JS引用CSS), 静态模块打包器可以记录每个模块的依赖,
引入需要的依赖(chunk), 生成文件依赖树, 为我们进行打包</li>
</ul>
<h4 id="webpack的核心概念">webpack的核心概念</h4>
<ul>
<li><strong>Entry</strong>入口,
指示webpack从那个文件作为入口开始打包文件, 分析内部依赖图</li>
<li><strong>Output</strong>输出, webpack输出的文件如何命名</li>
<li><strong>Loader</strong>让webpack识别css/img格式的文件(本体只能处理JS)</li>
<li><strong>Pulgins</strong>插件, 可以执行更复杂的任务,
例如打包压缩css/img</li>
<li><strong>Mode</strong>有两种对应模式
<ul>
<li>develop开发模式: 配置简单, 保证可以在本地调试运行</li>
<li>production生产模式: 启用更多插件, 优化代码运行</li>
</ul></li>
</ul>
<h3 id="基本使用">基本使用</h3>
<p>安装 <pre class="language-npm" data-language="npm"><code class="language-npm">sudo npm install webpack-cli -g
npm install webpack-cli webpack -dev
echo &#39;export PATH&#x3D;&quot;.&#x2F;node_modules&#x2F;.bin:$PATH&quot;&#39; &gt;&gt; ~&#x2F;.zshrc    # zsh安装</code></pre></p>
<p>运行 <pre class="language-npm" data-language="npm"><code class="language-npm">webpack .&#x2F;src&#x2F;js -o .&#x2F;build&#x2F; --mode&#x3D;development     # 开发模式 生成文件不压缩, 显示来自哪个文件
webpack .&#x2F;src&#x2F;js -o .&#x2F;build&#x2F; --mode&#x3D;production      # 生产模式 压缩内容与代码</code></pre></p>
<p>注意</p>
<ul>
<li>webpack本体可以处理js/json, 不能处理css/img等</li>
<li>可以将ES6自动转换为ES5</li>
<li>生产环境没有注释, 自动压缩代码</li>
</ul>
<h3 id="开发环境配置">开发环境配置</h3>
<h4 id="webpack配置文件">webpack配置文件</h4>
<p>webpack的配置文件是<code>webpack.config.js</code>,
应该与<code>node_modules</code>, <code>src</code>同文件夹,
由于使用了NodeJS, 所以采用CommonJS语法规范, 配置文件的格式是</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span>resolve<span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>      <span class="token comment">// 使用path调用目录绝对路径</span>

module<span class="token punctuation">.</span>exports<span class="token operator">=</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token string">'./src/js/index.js'</span><span class="token punctuation">,</span>         <span class="token comment">// 入口文件地址</span>
    <span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">"built.js"</span><span class="token punctuation">,</span> <span class="token comment">// string (default)</span>
        <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'build'</span><span class="token punctuation">)</span>   <span class="token comment">// 保存文件路径, 转换为绝对路径</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">module</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>
        <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">plugins</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">mode</span><span class="token operator">:</span> <span class="token string">'development'</span>
    <span class="token comment">// mode: 'production'</span>
<span class="token punctuation">&#125;</span> </code></pre>
<h4 id="打包cssless">打包css/less</h4>
<p>这里使用了额外的Loader:</p>
<ul>
<li><code>css-loader</code>: 将css转化为CommonJS模块,
内容是样式字符串</li>
<li><code>style-loader</code>: 将JS中的css样式资源创建style插入进去,
style指的是<code>&lt;head&gt;&lt;/head&gt;</code>中的<code>&lt;style&gt;&lt;/style&gt;</code>,
不是<code>&lt;div style=""&gt;&lt;/div&gt;</code></li>
</ul>
<p>安装npm包 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install style-loader css-loader -dev</code></pre> 配置文件 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span>resolve<span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>      <span class="token comment">// 使用path调用目录绝对路径</span>

module<span class="token punctuation">.</span>exports<span class="token operator">=</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token string">'./src/js/index.js'</span><span class="token punctuation">,</span>         <span class="token comment">// 入口文件地址</span>
    <span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">"built.js"</span><span class="token punctuation">,</span> <span class="token comment">// string (default)</span>
        <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'build'</span><span class="token punctuation">)</span>   <span class="token comment">// 保存文件路径, 转换为绝对路径</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">module</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>
        <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>
            <span class="token comment">// 匹配什么文件(以css结尾)</span>
            <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.css$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
            <span class="token comment">// css-loader可以将css转化为CommonJS模块, 内容是样式字符串</span>
            <span class="token comment">// style-loader可以JS中的css样式资源创建style插入进去</span>
            <span class="token comment">// 注意, 这里是&lt;style>&lt;/style>不是&lt;div style>&lt;/div></span>
            <span class="token comment">// 注意, use中的执行顺序是自右向左</span>
            <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'style-loader'</span><span class="token punctuation">,</span> <span class="token string">'css-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">]</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">plugins</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">mode</span><span class="token operator">:</span> <span class="token string">'development'</span>
    <span class="token comment">// mode: 'production'</span>
<span class="token punctuation">&#125;</span> </code></pre> index.js引入文件
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">import</span> sty <span class="token keyword">from</span> <span class="token string">'../css/a.css'</span></code></pre> 直接执行webpack <pre class="language-npm" data-language="npm"><code class="language-npm">webpack</code></pre></p>
<p>如果需要引入less, 需要:</p>
<ul>
<li>安装npm包 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install less less-loader -dev</code></pre></li>
<li>修改配置文件, rules中添加 <pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.less$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'style-loader'</span><span class="token punctuation">,</span> <span class="token string">'css-loader'</span><span class="token punctuation">,</span><span class="token string">'less-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li>JS直接引入文件 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">import</span> styl <span class="token keyword">from</span> <span class="token string">'../css/c.less'</span></code></pre></li>
</ul>
<h4 id="打包html">打包html</h4>
<p>需要使用额外的plugins <pre class="language-npm" data-language="npm"><code class="language-npm">npm install html-webpack-plugin </code></pre> 作为插件,
在使用的时候需要手动引入, webpack.config.js <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> HtmlWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span><span class="token string">'html-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// ...</span>
<span class="token literal-property property">plugins</span><span class="token operator">:</span><span class="token punctuation">[</span>
    <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">]</span></code></pre>
这里直接生成会发现build文件夹中多了一个index.html并且会自动引用所有输出资源,
想要指定压缩的html文件, 只需要 <pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">plugins</span><span class="token operator">:</span><span class="token punctuation">[</span>
  <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">template</span><span class="token operator">:</span> <span class="token string">'./src/index.html'</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">]</span></code></pre>
值得注意的是我们不要再次引用js资源了</p>
<h4 id="打包img">打包img</h4>
<p>==此内容适用于webpack4,
在webpack5中官方引入了4个模块处理资源文件==</p>
<p>安装Loader <pre class="language-npm" data-language="npm"><code class="language-npm">npm install url-loader file-loader -dev</code></pre> 配置文件,rules写入 <pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token comment">// 输入文件类型</span>
  <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(jpg|png|gif)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'url-loader'</span><span class="token punctuation">,</span>
    <span class="token comment">// 配置url-loader, 当文件大小小于8K的时候, 不打包压缩文件, 直接转译为Base64</span>
    <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">limit</span><span class="token operator">:</span> <span class="token number">8</span><span class="token operator">*</span><span class="token number">1024</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p>==如果在webpack5中还是想使用url-loader==</p>
<p>在<a
target="_blank" rel="noopener" href="https://webpack.docschina.org/guides/asset-modules/#resource-assets">官方文档</a>中写有</p>
<blockquote>
<p>当在 webpack 5 中使用旧的 assets loader（如
file-loader/url-loader/raw-loader 等）和 asset 模块时, 你可能想停止当前
asset 模块的处理, 并再次启动处理, 这可能会导致 asset 重复, 你可以通过将
asset 模块的类型设置为 'javascript/auto' 来解决。</p>
</blockquote>
<pre class="language-diff" data-language="diff"><code class="language-diff">&#123;
<span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> test: /\.(jpg|png|gif)$/,
</span><span class="token prefix unchanged"> </span><span class="token line"> use: [&#123;
</span><span class="token prefix unchanged"> </span><span class="token line">   loader: 'url-loader',
</span><span class="token prefix unchanged"> </span><span class="token line">   options: &#123;
</span><span class="token prefix unchanged"> </span><span class="token line">     limit: 8*1024,
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line">     esModule:false
</span></span><span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line">   &#125;
</span><span class="token prefix unchanged"> </span><span class="token line"> &#125;],
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> type: 'javascript/auto',
</span></span>&#125;</code></pre>
<p>==webpack5中的做法==</p>
<p>源模块类型(asset module type), 通过添加 4 种新的模块类型,
来替换所有这些 loader：</p>
<ul>
<li>asset/resource 发送一个单独的文件并导出 URL。之前通过使用
file-loader 实现。</li>
<li>asset/inline 导出一个资源的 data URI。之前通过使用 url-loader
实现。</li>
<li>asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。</li>
<li>asset 在导出一个 data URI
和发送一个单独的文件之间自动选择。之前通过使用 url-loader,
并且配置资源体积限制实现。</li>
</ul>
<p>无需安装npm, 只要在配置rulesrules加入 <pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(png|jpg|gif)</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'asset/resource'</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p>以上的方法只能处理css中引入的文件, 对于html中的img文件无法处理,
可以使用html-loader <pre class="language-npm" data-language="npm"><code class="language-npm">npm install html-loader</code></pre> 加入rules <pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.html$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'html-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.html$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'html-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p>可以看到, webpack会修改文件名, 修改后名字是图片的Hash, 同时注意到,
虽然我们在html与css中两次对同一文件进行引用, 但是webpack只打包了一次</p>
<h4 id="打包其他资源">打包其他资源</h4>
<p>还可能打包一些不需要压缩的资源(例如字体文件)</p>
<p>加入rules <pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(css|js|html|less)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'file-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<h4 id="devserver">devserver</h4>
<p>我们希望实现webpack自动化构建, 实现自动编译, 自动发开浏览器,
自动刷新浏览器, 需要使用模块<code>webpack-dev-server</code></p>
<p>安装 <pre class="language-none"><code class="language-none">npm i webpack-dev-server </code></pre> 配置JS, 在最外层, 与mode同级, 在mode之后
<pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">devServer</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">compress</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>     <span class="token comment">// 使用gzip压缩</span>
  <span class="token literal-property property">port</span><span class="token operator">:</span> <span class="token number">3000</span>
<span class="token punctuation">&#125;</span></code></pre> 注意, 自动化的构建在内存中进行, 并没有输出
<pre class="language-none"><code class="language-none">npx webpack-dev-server  </code></pre></p>
<h4 id="开发环境配置-1">开发环境配置</h4>
<pre class="language-npm" data-language="npm"><code class="language-npm">sudo npm install webpack-cli -g
echo &#39;export PATH&#x3D;&quot;.&#x2F;node_modules&#x2F;.bin:$PATH&quot;&#39; &gt;&gt; ~&#x2F;.zshrc
npm install webpack-cli webpack style-loader css-loader less less-loader html-webpack-plugin html-loader --include&#x3D;dev</code></pre>
<p><code>webpack.config.js</code> <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span>resolve<span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> HtmlWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span><span class="token string">'html-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

module<span class="token punctuation">.</span>exports<span class="token operator">=</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token string">'./src/js/index.js'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">"built.js"</span><span class="token punctuation">,</span>
        <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'build'</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">module</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>
        <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.css$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'style-loader'</span><span class="token punctuation">,</span> <span class="token string">'css-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.less$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'style-loader'</span><span class="token punctuation">,</span> <span class="token string">'css-loader'</span><span class="token punctuation">,</span><span class="token string">'less-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(png|jpg|gif)</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'asset/resource'</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.html$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'html-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(css|js|html|less)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'file-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span>
    <span class="token punctuation">]</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">plugins</span><span class="token operator">:</span><span class="token punctuation">[</span>
        <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">template</span><span class="token operator">:</span> <span class="token string">'./src/index.html'</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">mode</span><span class="token operator">:</span> <span class="token string">'development'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">devServer</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>
        <span class="token literal-property property">compress</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>     <span class="token comment">// 使用gzip压缩</span>
        <span class="token literal-property property">port</span><span class="token operator">:</span> <span class="token number">3000</span><span class="token punctuation">,</span>
        <span class="token literal-property property">open</span><span class="token operator">:</span> <span class="token boolean">true</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span> </code></pre></p>
<h3 id="生产环境配置">生产环境配置</h3>
<p>与开发环境不同的是, 生产环境要求</p>
<ul>
<li>CSS文件从JS文件中分离</li>
<li>对代码进行合并压缩</li>
<li>样式代码与JS代码进行低版本兼容</li>
</ul>
<h4 id="提取css为单独文件">提取CSS为单独文件</h4>
<p>提取单独文件需要插件:
<code>mini-css-extract-plugin</code>与对应的Loader:
<code>MiniCssExtractPlugin.loader</code> <pre class="language-npm" data-language="npm"><code class="language-npm">npm install mini-css-extract-plugin -dev</code></pre> 配置文件
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> resolve <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> HtmlWebpackPulgin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'html-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> MiniCssExtractPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mini-css-extract-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token string">'./src/js/index.js'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'js/built.js'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'built'</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">module</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.css$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span>
                MiniCssExtractPlugin<span class="token punctuation">.</span>loader<span class="token punctuation">,</span> <span class="token comment">// JS -> .css</span>
             <span class="token comment">// 'style-loader',         // JS -> &lt;style>&lt;/style></span>
                <span class="token string">'css-loader'</span><span class="token punctuation">]</span>           <span class="token comment">// 作用是 CSS -> JS</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">]</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPulgin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">template</span><span class="token operator">:</span> <span class="token string">'./src/index.html'</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">MiniCssExtractPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'css/built.css'</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token literal-property property">mode</span><span class="token operator">:</span> <span class="token string">'production'</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<h4 id="css兼容性处理">CSS兼容性处理</h4>
<p>需要Loader与插件postcss-loader(转译),
postcss-preset-env精确兼容性到浏览器 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install postcss-loader postcss-preset-env -d </code></pre> 配置文件</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> resolve <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> HtmlWebpackPulgin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'html-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> MiniCssExtractPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mini-css-extract-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_ENV</span> <span class="token operator">=</span> <span class="token string">'development'</span><span class="token punctuation">;</span>     <span class="token comment">// 兼容性模式, 默认是production, 与mode无关</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token string">'./src/js/index.js'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'js/built.js'</span><span class="token punctuation">,</span>
        <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'built'</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token literal-property property">module</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.css$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
            <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span>
                MiniCssExtractPlugin<span class="token punctuation">.</span>loader<span class="token punctuation">,</span>
                <span class="token string">'css-loader'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
                    <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">"postcss-loader"</span><span class="token punctuation">,</span>   <span class="token comment">// 因为需要配置选项, 要写成对象</span>
                    <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                        <span class="token literal-property property">postcssOptions</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>       <span class="token comment">// 内部不用管</span>
                            <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"postcss-preset-env"</span><span class="token punctuation">]</span><span class="token punctuation">]</span>
                        <span class="token punctuation">&#125;</span>
                    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
                <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
            <span class="token punctuation">]</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">]</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPulgin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">template</span><span class="token operator">:</span> <span class="token string">'./src/index.html'</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">MiniCssExtractPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
            <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'css/built.css'</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">mode</span><span class="token operator">:</span> <span class="token string">'production'</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>对于浏览器配置, 还需要修改包所在的package.json <pre class="language-json" data-language="json"><code class="language-json"><span class="token punctuation">&#123;</span>
  <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"demo2"</span><span class="token punctuation">,</span>
  <span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span>
  <span class="token comment">// ...</span>
  <span class="token property">"browserslist"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token property">"development"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token string">"last 1 chrome version"</span><span class="token punctuation">,</span>
      <span class="token string">"last 1 firefox version"</span><span class="token punctuation">,</span>
      <span class="token string">"last 1 safari version"</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token property">"production"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token string">">0.02%"</span><span class="token punctuation">,</span>
      <span class="token string">"not dead"</span><span class="token punctuation">,</span>
      <span class="token string">"not op_mini all"</span>
    <span class="token punctuation">]</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p>分别设置了开发模式兼容性与生产模式兼容性,
其中<code>"last 1 chrome version"</code>表示只兼容最新版本Chrome,<code>"&gt;0.02%"</code>表示兼容99.98%的浏览器,
<code>"not dead"</code>表示不管已经死的浏览器,
<code>"not op_mini all"</code>不管欧朋浏览器, 更多配置见<a
target="_blank" rel="noopener" href="https://www.npmjs.com/package/postcss-loader#config">官方文档</a>,
可以使用<code>npx browserslist</code>查看支持的浏览器</p>
<h4 id="压缩css">压缩CSS</h4>
<p>需要插件css-minimizer-webpack-plugin <pre class="language-none"><code class="language-none">npm install css-minimizer-webpack-plugin -dev</code></pre> 配置文件
<pre class="language-diff" data-language="diff"><code class="language-diff"><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
</span></span>plugins: [
<span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> new HtmlWebpackPulgin(&#123;
</span><span class="token prefix unchanged"> </span><span class="token line">   template: './src/index.html'
</span><span class="token prefix unchanged"> </span><span class="token line"> &#125;), new MiniCssExtractPlugin(&#123;
</span><span class="token prefix unchanged"> </span><span class="token line">   filename: 'css/built.css'
</span><span class="token prefix unchanged"> </span><span class="token line"> &#125;), 
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> new CssMinimizerWebpackPlugin()
</span></span>],</code></pre></p>
<h4 id="es语法检查">ES语法检查</h4>
<p>ESLint可以根据配置纠正JS文件的语法错误与风格不统一的问题(实际上可以直接使用VSCODE的插件实现),
我们采用爱彼迎的JS规范: <a
target="_blank" rel="noopener" href="https://github.com/airbnb/javascript">英文文档</a>, <a
target="_blank" rel="noopener" href="https://github.com/lin-123/javascript">中文文档</a></p>
<pre class="language-npm" data-language="npm"><code class="language-npm">npm install eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import -dev</code></pre>
<p>修改配置文件(rules中追加) <pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">node_modules</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token comment">// 不修复别人的代码</span>
  <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'eslint-loader'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 自动修复 eslint 的错误</span>
    <span class="token literal-property property">fix</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span></code></pre>
修改<code>package.json</code>(与version同层) <pre class="language-json" data-language="json"><code class="language-json"><span class="token property">"eslintConfig"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token property">"extends"</span><span class="token operator">:</span> <span class="token string">"airbnb-base"</span><span class="token punctuation">,</span>
  <span class="token property">"env"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token property">"browser"</span><span class="token operator">:</span> <span class="token boolean">true</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<h4 id="js兼容性">JS兼容性</h4>
<p>兼容JS需要使用Babel <pre class="language-npm" data-language="npm"><code class="language-npm">npm install babel-loader \
@babel&#x2F;core @babel&#x2F;preset-env core-js \
@babel&#x2F;polyfill -dev</code></pre> 第一行是Loader,
第二行还是Babel的依赖, 第三行是高级语法预设</p>
<p>新增rules <pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">node_modules</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'babel-loader'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 预设:指示 babel 做怎么样的兼容性处理</span>
    <span class="token literal-property property">presets</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">[</span>
        <span class="token string">'@babel/preset-env'</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#123;</span>
          <span class="token comment">// 按需加载</span>
          <span class="token literal-property property">useBuiltIns</span><span class="token operator">:</span> <span class="token string">'usage'</span><span class="token punctuation">,</span>
          <span class="token comment">// 指定 core-js 版本</span>
          <span class="token literal-property property">corejs</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
            <span class="token literal-property property">version</span><span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span>
          <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token comment">// 指定兼容性做到哪个版本浏览器</span>
          <span class="token literal-property property">targets</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
            <span class="token literal-property property">chrome</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">firefox</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">ie</span><span class="token operator">:</span> <span class="token string">'9'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">safari</span><span class="token operator">:</span> <span class="token string">'10'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">edge</span><span class="token operator">:</span> <span class="token string">'17'</span><span class="token punctuation">,</span>
          <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<h4 id="js压缩">JS压缩</h4>
<p>修改mode为<code>production</code>即可</p>
<h4 id="html压缩">html压缩</h4>
<p>修改Plugin <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPulgin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">template</span><span class="token operator">:</span> <span class="token string">'./src/index.html'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">minify</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">collapseWhitespace</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token literal-property property">removeComments</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span></code></pre></p>
<h4 id="生产环境配置-1">生产环境配置</h4>
<p>安装依赖 <pre class="language-npm" data-language="npm"><code class="language-npm">sudo npm install webpack-cli -g
echo &#39;export PATH&#x3D;&quot;.&#x2F;node_modules&#x2F;.bin:$PATH&quot;&#39; &gt;&gt; ~&#x2F;.zshrc
npm install -dev webpack webpack-cli @babel&#x2F;core @babel&#x2F;polyfill @babel&#x2F;preset-env babel-loader core-js css-loader eslint eslint-config-airbnb-base eslint-loader eslint-plugin-import file-loader html-loader html-webpack-plugin less less-loader postcss-loader postcss-preset-env style-loader devDependencies css-minimizer-webpack-plugin mini-css-extract-plugin</code></pre> webpack.config.js文件 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> resolve <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> HtmlWebpackPulgin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'html-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> MiniCssExtractPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'mini-css-extract-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> CssMinimizerWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'css-minimizer-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_ENV</span> <span class="token operator">=</span> <span class="token string">'production'</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> commonCssLoader <span class="token operator">=</span> <span class="token punctuation">[</span>
  MiniCssExtractPlugin<span class="token punctuation">.</span>loader<span class="token punctuation">,</span>
  <span class="token string">'css-loader'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'postcss-loader'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">postcssOptions</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span>
          <span class="token punctuation">[</span><span class="token string">'postcss-preset-env'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token string">'./src/js/index.js'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'js/built.js'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'built'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">module</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.css$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token operator">...</span>commonCssLoader<span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.less$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token operator">...</span>commonCssLoader<span class="token punctuation">,</span> <span class="token string">'less-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">node_modules</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'eslint-loader'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">fix</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">node_modules</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'babel-loader'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">presets</span><span class="token operator">:</span> <span class="token punctuation">[</span>
          <span class="token punctuation">[</span>
            <span class="token string">'@babel/preset-env'</span><span class="token punctuation">,</span>
            <span class="token punctuation">&#123;</span>
              <span class="token literal-property property">useBuiltIns</span><span class="token operator">:</span> <span class="token string">'usage'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">corejs</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                <span class="token literal-property property">version</span><span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span>
              <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
              <span class="token literal-property property">targets</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                <span class="token literal-property property">chrome</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
                <span class="token literal-property property">firefox</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
                <span class="token literal-property property">ie</span><span class="token operator">:</span> <span class="token string">'9'</span><span class="token punctuation">,</span>
                <span class="token literal-property property">safari</span><span class="token operator">:</span> <span class="token string">'10'</span><span class="token punctuation">,</span>
                <span class="token literal-property property">edge</span><span class="token operator">:</span> <span class="token string">'17'</span><span class="token punctuation">,</span>
              <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(png|jpg|gif)</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'asset/resource'</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.html$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'html-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(js|css|less|html|jpg|png|gif)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'file-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPulgin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
      <span class="token literal-property property">template</span><span class="token operator">:</span> <span class="token string">'./src/index.html'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">minify</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">collapseWhitespace</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
        <span class="token literal-property property">removeComments</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">MiniCssExtractPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
      <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'css/built.css'</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">CssMinimizerWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">mode</span><span class="token operator">:</span> <span class="token string">'production'</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre>
package.json文件(version同级别) <pre class="language-json" data-language="json"><code class="language-json"><span class="token property">"browserslist"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token property">"development"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token string">"last 1 chrome version"</span><span class="token punctuation">,</span>
    <span class="token string">"last 1 firefox version"</span><span class="token punctuation">,</span>
    <span class="token string">"last 1 safari version"</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token property">"production"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token string">">0.02%"</span><span class="token punctuation">,</span>
    <span class="token string">"not dead"</span><span class="token punctuation">,</span>
    <span class="token string">"not op_mini all"</span>
  <span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token property">"eslintConfig"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token property">"extends"</span><span class="token operator">:</span> <span class="token string">"airbnb-base"</span><span class="token punctuation">,</span>
  <span class="token property">"env"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token property">"browser"</span><span class="token operator">:</span> <span class="token boolean">true</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<h3 id="webpack配置优化">webpack配置优化</h3>
<ul>
<li>开发环境性能优化
<ul>
<li>优化webpack的打包构建速度(HMR)<br />
</li>
<li>优化代码调试(source map)<br />
</li>
</ul></li>
<li>生产环境性能功能优化
<ul>
<li>优化打包速度</li>
<li>优化代码性能</li>
</ul></li>
</ul>
<h3 id="开发环境配置优化">开发环境配置优化</h3>
<h4 id="模块热替换hmr">模块热替换HMR</h4>
<p>存在问题, 当一个文件变化时, 全部文件都会重新打包, 希望与GLUP一样,
实现文件热更新</p>
<ul>
<li><code>devServer</code>中添加属性<code>hot = true</code></li>
<li>修改入口文件:
<code>entry: ['./src/js/index.js', './src/index.html']</code></li>
<li>修改JS文件, 在末尾加入: <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">if</span><span class="token punctuation">(</span>module<span class="token punctuation">.</span>hot<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>     <span class="token comment">// 如果开启了热加载</span>
    module<span class="token punctuation">.</span>hot<span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span><span class="token string">'test.js'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>   <span class="token comment">// 监控test文件, 如果变化不重新编译, 只调用回调函数</span>
        <span class="token function">work</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span></code></pre></li>
</ul>
<h4 id="sourcemap">SourceMap</h4>
<p>与less编译的时候我们需要map文件确定样式对应到哪里一样,
编译后的JS也应该提供类似的功能方便报错后的调试,
只需要与<code>devServer</code>同级别设置 <pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">devtool</span><span class="token operator">:</span> <span class="token string">'source-map'</span></code></pre> 即可,
其中值可以为<code>[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map</code>,
分别表示</p>
<ul>
<li><p>source-map：外部<br />
错误代码准确信息 和 源代码的错误位置<br />
</p></li>
<li><p>inline-source-map：内联<br />
只生成一个内联source-map<br />
错误代码准确信息 和 源代码的错误位置<br />
</p></li>
<li><p>hidden-source-map：外部<br />
错误代码错误原因，但是没有错误位置<br />
不能追踪源代码错误，只能提示到构建后代码的错误位置<br />
</p></li>
<li><p>eval-source-map：内联<br />
每一个文件都生成对应的source-map，都在eval<br />
错误代码准确信息 和 源代码的错误位置<br />
</p></li>
<li><p>nosources-source-map：外部<br />
错误代码准确信息, 但是没有任何源代码信息<br />
</p></li>
<li><p>cheap-source-map：外部<br />
错误代码准确信息 和 源代码的错误位置<br />
只能精确的行<br />
</p></li>
<li><p>cheap-module-source-map：外部<br />
错误代码准确信息 和 源代码的错误位置<br />
module会将loader的source map加入</p></li>
<li><p>内联 和 外部的区别：</p>
<ul>
<li>外部生成了文件，内联没有<br />
</li>
<li>内联构建速度更快</li>
</ul></li>
<li><p>开发环境：速度快，调试更友好</p>
<ul>
<li>速度快(eval&gt;inline&gt;cheap&gt;...)<br />
eval-cheap-souce-map<br />
eval-source-map<br />
</li>
<li>调试更友好<br />
souce-map<br />
cheap-module-souce-map<br />
cheap-souce-map<br />
</li>
<li>最终选择: eval-source-map / eval-cheap-module-souce-map</li>
</ul></li>
<li><p>生产环境：源代码要不要隐藏? 调试要不要更友好<br />
内联会让代码体积变大，所以在生产环境不用内联<br />
nosources-source-map 全部隐藏<br />
hidden-source-map 只隐藏源代码，会提示构建后代码错误信息</p>
<ul>
<li>最终选择: source-map / cheap-module-souce-map</li>
</ul></li>
</ul>
<h3 id="生产环境配置优化">生产环境配置优化</h3>
<h4 id="oneof">oneOf</h4>
<p>在webpack的时候, 每一个文件都要与所有的规则匹配, 检查后缀是否满足,
造成性能损耗, 可以使用oneOf表示一旦文件成功匹配就不再与之后的规则匹配,
同时要求, 不能有两类rule匹配同一个文件, 使用如下 <pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">module</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span> <span class="token comment">// 不得有两个文件匹配js, 所以eslint单独拿出来</span>
    <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
    <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">node_modules</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
    <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'eslint-loader'</span><span class="token punctuation">,</span>
    <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">fix</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">oneOf</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span><span class="token comment">// 加入oneOf</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.css$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token operator">...</span>commonCssLoader<span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.less$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token operator">...</span>commonCssLoader<span class="token punctuation">,</span> <span class="token string">'less-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">node_modules</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'babel-loader'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">presets</span><span class="token operator">:</span> <span class="token punctuation">[</span>
          <span class="token punctuation">[</span>
            <span class="token string">'@babel/preset-env'</span><span class="token punctuation">,</span>
            <span class="token punctuation">&#123;</span>
              <span class="token literal-property property">useBuiltIns</span><span class="token operator">:</span> <span class="token string">'usage'</span><span class="token punctuation">,</span>
              <span class="token literal-property property">corejs</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                <span class="token literal-property property">version</span><span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span>
              <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
              <span class="token literal-property property">targets</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
                <span class="token literal-property property">chrome</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
                <span class="token literal-property property">firefox</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
                <span class="token literal-property property">ie</span><span class="token operator">:</span> <span class="token string">'9'</span><span class="token punctuation">,</span>
                <span class="token literal-property property">safari</span><span class="token operator">:</span> <span class="token string">'10'</span><span class="token punctuation">,</span>
                <span class="token literal-property property">edge</span><span class="token operator">:</span> <span class="token string">'17'</span><span class="token punctuation">,</span>
              <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
            <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(png|jpg|gif)</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">'asset/resource'</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.html$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'html-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(js|css|less|html|jpg|png|gif)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
      <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'file-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span></code></pre></p>
<h4 id="缓存相关">缓存相关</h4>
<p>与生产环境HRM类似, 在每次重新构建的时候不希望Babel编译未修改模块,
修改JS文件配置</p>
<pre class="language-diff" data-language="diff"><code class="language-diff">&#123;
<span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> test: /\.js$/,
</span><span class="token prefix unchanged"> </span><span class="token line"> exclude: /node_modules/,
</span><span class="token prefix unchanged"> </span><span class="token line"> loader: 'babel-loader',
</span><span class="token prefix unchanged"> </span><span class="token line"> options: &#123;
</span><span class="token prefix unchanged"> </span><span class="token line">   presets: [...],
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line">   cacheDirectory: true,
</span></span><span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> &#125;,
</span></span>&#125;</code></pre>
<p>我们还希望用户可以缓存我们的资源文件(在后端路由的时候添加规则),
这是需要修改输出文件名, 方便出现Bug强制清除用户缓存 <pre class="language-diff" data-language="diff"><code class="language-diff">output: &#123;
<span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line"> filename: 'js/built.js',
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> filename: 'js/built.[chunkhash:10].js',
</span></span><span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> path: resolve(__dirname, 'built'),
</span></span>&#125;
//...
new MiniCssExtractPlugin(&#123;
<span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line"> filename: 'css/built.css',
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> filename: 'css/built.[chunkhash:10].css',
</span></span>&#125;)</code></pre></p>
<h4 id="tree-shaking">tree shaking</h4>
<p>剪掉没有被调用的JS/CSS代码, 要求：</p>
<ol type="1">
<li>必须使用ES6模块化<br />
</li>
<li>开启production环境</li>
</ol>
<p>部分webpack版本会删除css文件,
需要在package.json中设置<code>"sideEffects": ["*.css", "*.less"]</code>(与name同级)</p>
<h4 id="code-split">code split</h4>
<p>我们不希望所有的文件都合并成bindle.js,
希望可以按照我们的要求分成多个js模块, 可以修改入口与输出文件实现</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">index</span><span class="token operator">:</span> <span class="token string">'./src/js/index.js'</span><span class="token punctuation">,</span>     <span class="token comment">// 多入口文件, 与输出名</span>
  <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token string">'./src/js/test.js'</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'js/[name].[contenthash:10].js'</span><span class="token punctuation">,</span>    <span class="token comment">// 输出文件名要修改成name.hash.js否则会重名</span>
  <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'built'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token comment">// ...</span>
<span class="token literal-property property">optimization</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>     <span class="token comment">// 将node_modules中模大块单独打包</span>
  <span class="token literal-property property">splitChunks</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">chunks</span><span class="token operator">:</span> <span class="token string">'all'</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span></code></pre>
<p>如果我们写的是单页面应用, 只需要一个js文件,
但是我们还是想要实现多输出, 可以通过JS代码实现</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token string">'./src/js/index.js'</span><span class="token punctuation">,</span>       <span class="token comment">// 单入口输入</span>
<span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'js/[name].[contenthash:10].js'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'built'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token literal-property property">optimization</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>     <span class="token comment">// 将node_modules中模大块单独打包</span>
  <span class="token literal-property property">splitChunks</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">chunks</span><span class="token operator">:</span> <span class="token string">'all'</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span></code></pre>
<p><code>index.js</code>文件 <pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">/*
  通过js代码，让某个文件被单独打包成一个chunk
  import动态导入语法：能将某个文件单独打包
  注意, 文件名是用注释指定的
*/</span>
<span class="token keyword">import</span><span class="token punctuation">(</span><span class="token comment">/* webpackChunkName: 'test' */</span><span class="token string">'./test'</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">&#123;</span> mul<span class="token punctuation">,</span> count <span class="token punctuation">&#125;</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 文件加载成功~</span>
    <span class="token comment">// eslint-disable-next-line</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token comment">/*...*/</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// eslint-disable-next-line</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'文件加载失败~'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></p>
<h4 id="js文件的懒加载与预加载">JS文件的懒加载与预加载</h4>
<ul>
<li>懒加载: 在需要的时候再加载JS文件, 例如在调用库中函数的时候再加载,
而不是在import的时候加载</li>
<li>预加载: 在懒加载之间, 当浏览器空闲的时候偷偷加载文件</li>
</ul>
<p>我们需要修改JS文件实现:</p>
<p>原index.js <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> showMe <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'./test'</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'INDEX-load'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#btn'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function-variable function">onclick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  <span class="token function">showMe</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre> 原test.js <pre class="language-js" data-language="js"><code class="language-js">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'TEST-load'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">showMe</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"TEST-OK"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
在浏览器点击按键前会输出两个<code>XXX-load</code>,
点击按键之后输出<code>XX-OK</code><br />
我们希望实现的效果是, 点击按钮前出现<code>INDEX-load</code>,
点击按钮后出现<code>TEST-load</code>, <code>TEST-ok</code></p>
<p>修改index.js <pre class="language-js" data-language="js"><code class="language-js">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'INDEX-load'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#btn'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function-variable function">onclick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">'./test'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">&#123;</span> showMe <span class="token punctuation">&#125;</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token function">showMe</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre> 直接打包即可</p>
<p>注意到, 在第一次使用showMe的时候, test文件会被懒加载进来,
但是在第二次使用的时候, 由于test已经被加入缓存,
所以不会重复请求test文件</p>
<p>默认情况下test文件会被打上id作为输出文件名, 可以指定输出文件名,
并设置预加载 <pre class="language-js" data-language="js"><code class="language-js">console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'INDEX-load'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#btn'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function-variable function">onclick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
  <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token comment">/* webpackChunkName: 'test', webpackPrefetch: true */</span><span class="token string">'./test'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">&#123;</span> showMe <span class="token punctuation">&#125;</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token function">showMe</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre></p>
<p>这样设置后, 在打开浏览器我们可以看到<code>INDEX-load</code>,
没有<code>TEST-load</code>,
但是在网络选项卡中可以看到<code>test.[hash].js</code>已经被加载了,
点击按钮, 没有重复请求,
同时输出<code>TEST-load</code>与<code>TEST-ok</code></p>
<p>注意, 预加载可能存在兼容性问题</p>
<h4 id="渐进式网页应用pwa离线可访问">渐进式网页应用PWA(离线可访问)</h4>
<p>我们希望实现离线仍然可以尽力访问大部分内容, 典型的页面有<a
target="_blank" rel="noopener" href="https://v3.cn.vuejs.org/">Vue</a>(一大特点是地址栏旁边有一个安装XXX)</p>
<p>使用workbox实现 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install -dev workbox-webpack-plugin</code></pre> 修改配置文件 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> WorkboxWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'workbox-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// ...</span>
<span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span>
  <span class="token comment">// ...</span>
  <span class="token keyword">new</span> <span class="token class-name">WorkboxWebpackPlugin<span class="token punctuation">.</span>GenerateSW</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">clientsClaim</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token comment">// 使用最新的service worker</span>
    <span class="token literal-property property">skipWaiting</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token comment">// 快速启动</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span></code></pre>
index.js后追加 <pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token string">'serviceWorker'</span> <span class="token keyword">in</span> navigator<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">// 是否支持Service-worker</span>
  window<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'load'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 有的话在全局加载结束后注册事件</span>
    navigator<span class="token punctuation">.</span>serviceWorker<span class="token punctuation">.</span><span class="token function">register</span><span class="token punctuation">(</span><span class="token string">'./service-worker.js'</span><span class="token punctuation">)</span> <span class="token comment">// 注册一个serviceworker, 这个JS文件会在webpack的时候自动生成</span>
      <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
      <span class="token comment">// 加载成功...</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'SW-On'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'SW-Err'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre> 如果开启了ESLint的话,
还需要在package.json中配置以支持全局变量(与name同级) <pre class="language-json" data-language="json"><code class="language-json"><span class="token property">"eslintConfig"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token property">"extends"</span><span class="token operator">:</span> <span class="token string">"airbnb-base"</span><span class="token punctuation">,</span>
  <span class="token property">"env"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token property">"browser"</span><span class="token operator">:</span> <span class="token boolean">true</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<h4 id="多进程打包">多进程打包</h4>
<p>安装依赖 <pre class="language-npm" data-language="npm"><code class="language-npm">npm install --save-dev thread-loader</code></pre> 比较耗时的是babel, 我们为Babel添加,
在<code>Babel-loader</code>前面添加<code>thread-loader</code></p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
<span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
<span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">node_modules</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
<span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'thread-loader'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">workers</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token comment">// 使用双进程(不写就是满进程运行)</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'babel-loader'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">presets</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">[</span>
        <span class="token string">'@babel/preset-env'</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#123;</span>
          <span class="token literal-property property">useBuiltIns</span><span class="token operator">:</span> <span class="token string">'usage'</span><span class="token punctuation">,</span>
          <span class="token literal-property property">corejs</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
            <span class="token literal-property property">version</span><span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span>
          <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token literal-property property">targets</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
            <span class="token literal-property property">chrome</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">firefox</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">ie</span><span class="token operator">:</span> <span class="token string">'9'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">safari</span><span class="token operator">:</span> <span class="token string">'10'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">edge</span><span class="token operator">:</span> <span class="token string">'17'</span><span class="token punctuation">,</span>
          <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span></code></pre>
<p>还是注意, JS是单进程, 开启多进程后需要占用额外的时间,
所以只有工作消耗时间长的时候我们才开启多进程(例如Babel)</p>
<h4 id="externals禁止打包">externals禁止打包</h4>
<p>一部分包(例如jQuery)我们可能希望在本地使用npm引入,
但是上线后使用CDN引入, 可以将这些包写入排除打包列表,
然后在html文件中手动引入CDN</p>
<p>与mode同级追加 <pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">externals</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">// 忽略库名 npm包名</span>
  <span class="token literal-property property">jquery</span><span class="token operator">:</span> <span class="token string">'jQuery'</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">,</span></code></pre></p>
<h4 id="ddl动态链接库">ddl动态链接库</h4>
<p>与external类似, 指示webpack哪些库不需要打包,
同时dll支持将指定多个第三方库打包成一个js, 创建新的配置文件用于打包</p>
<p>与<code>webpack.config.js</code>同级创建<code>webpack.dll.js</code>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span> resolve <span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> webpack <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'webpack'</span><span class="token punctuation">)</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">jquery</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'jquery'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token comment">// 要打包的是生成一个jquery, 这个jquery包含的包有(数组里指定的)jquery</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'[name].js'</span><span class="token punctuation">,</span> <span class="token comment">// 输出就是名字.js</span>
    <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'dll'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// 输出路径</span>
    <span class="token literal-property property">library</span><span class="token operator">:</span> <span class="token string">'[name]_[hash]'</span><span class="token punctuation">,</span> <span class="token comment">// 别人在调用我的时候使用的包名叫什么</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token comment">// 创建一个manifest.json告诉webpack上面打包的文件不需要打包, 已经被dll打包到哪里了</span>
    <span class="token keyword">new</span> <span class="token class-name">webpack<span class="token punctuation">.</span>DllPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
      <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'[name]_[hash]'</span><span class="token punctuation">,</span>
      <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'dll/manifest.json'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre></p>
<pre class="language-npm" data-language="npm"><code class="language-npm">webpack --config webpack.dll.js </code></pre>
<p>此时, 我们完成了第三方库的自定义打包</p>
<p>之后, 我们还要告诉webpack</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">// 告诉 webpack 哪些库不参与打包, 虽然在JS中import了jquery, webpack也是会忽略</span>
<span class="token keyword">new</span> <span class="token class-name">webpack<span class="token punctuation">.</span>DllReferencePlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">manifest</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'dll/manifest.json'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token comment">// 设置哪些包应该在html中自动引入</span>
<span class="token keyword">new</span> <span class="token class-name">AddAssetHtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">filepath</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'dll/jquery.js'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">,</span></code></pre>
<p>最后webpack源文件 <pre class="language-none"><code class="language-none">webpack</code></pre></p>
<h3 id="基本属性详细配置">基本属性详细配置</h3>
<h4 id="entry">Entry</h4>
<p>entry键有几种值</p>
<ul>
<li>String: './src/js/index.js'指定一个输入文件, 打包生成一个chunk,
输出一个文件(默认main.js)</li>
<li>Array: <code>['./src/js/index.js', './src/js/test.js']</code>
指定多个输入文件, 但是只会有一个输出文件,
<strong>一般只用于HMR的HTML热更新生效</strong></li>
<li>Object:
<code>&#123;index: './src/js/index.js', add: './src/js/add.js'&#125;</code>
指定多个输出文件, 输出文件名就是键名</li>
<li>Object混合:
<code>&#123;index: ['./src/js/index.js', './src/js/test.js'], add: ['./src/js/add.js', './src/js/test.js']&#125;</code>
指定多个输出文件, 输出文件名就是键名, 一个文件可能包含多个包</li>
</ul>
<h4 id="output">output</h4>
<p>常见形式 <pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">// 输出文件名</span>
  <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'js/built.js'</span><span class="token punctuation">,</span>
  <span class="token comment">// 输出文件目录</span>
  <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'build'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token comment">// 输出公共路径</span>
  <span class="token literal-property property">publicPath</span><span class="token operator">:</span> <span class="token string">'/'</span>
<span class="token punctuation">&#125;</span></code></pre>
最后的输出路径就是<code>path+filename</code>,
<code>publicPath</code>一般用于生产环境,
加上<code>publicPath: '/path/'</code>,
在请求的时候会进行请求路径<code>yourdomain.com/path/...</code></p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">// 输出文件名</span>
  <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">'js/built.js'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'build'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token literal-property property">chunkFilename</span><span class="token operator">:</span> <span class="token string">'js/[name]_chunk.js'</span><span class="token punctuation">,</span> <span class="token comment">// 非入口chunk的名称</span>
  <span class="token literal-property property">library</span><span class="token operator">:</span> <span class="token string">'[name]'</span><span class="token punctuation">,</span> <span class="token comment">// 整个库向外暴露的变量名</span>
  <span class="token comment">// libraryTarget: 'window' // 将整个库向外暴露变量, 添加到哪个上, 用于 browser </span>
  <span class="token comment">// libraryTarget: 'global' // 将整个库向外暴露变量, 添加到哪个上, 用于 node</span>
  <span class="token comment">// libraryTarget: 'commonjs' // 使用模块规范进行暴露</span>
<span class="token punctuation">&#125;</span></code></pre>
<h3 id="module">module</h3>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">module</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.css$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
    <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'style-loader'</span><span class="token punctuation">,</span> <span class="token string">'css-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token comment">// 多Loader</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.html$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>                    <span class="token comment">// 使用文件</span>
    <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'html-loader'</span><span class="token punctuation">,</span>              <span class="token comment">// 单个Loader</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(css|js|html|less)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>   <span class="token comment">// 排除文件</span>
    <span class="token literal-property property">enforce</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>                      <span class="token comment">// 优先执行</span>
    <span class="token literal-property property">enforce</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>                     <span class="token comment">// 不优先执行</span>
    <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'file-loader'</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">oneOf</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>                           <span class="token comment">// 只出现一次</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span></code></pre>
<h3 id="resolve">resolve</h3>
<p>用于配置解析模块的规则(在mode后)</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">// 解析模块的规则</span>
<span class="token literal-property property">resolve</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">// 配置解析模块路径别名: 优点简写路径 缺点路径没有提示</span>
  <span class="token literal-property property">alias</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">$css</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'src/css'</span><span class="token punctuation">)</span>
    <span class="token comment">// 以后在引用css的时候只需要`import $css/style.css`</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token comment">// 配置省略文件路径的后缀名</span>
  <span class="token literal-property property">extensions</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'.js'</span><span class="token punctuation">,</span> <span class="token string">'.json'</span><span class="token punctuation">,</span> <span class="token string">'.jsx'</span><span class="token punctuation">,</span> <span class="token string">'.css'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token comment">// 告诉 webpack 解析模块是去找哪个目录(默认是node_modules, ../node_modules, ../../node_modules, ...)</span>
  <span class="token literal-property property">modules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'../../node_modules'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">'node_modules'</span><span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span></code></pre>
<h3 id="devserver-1">devServer</h3>
<p>注意是用于开发环境哈</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">devServer</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">// 运行代码的目录</span>
  <span class="token literal-property property">contentBase</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'build'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token comment">// 监视 contentBase 目录下的所有文件，一旦文件变化就会 reload</span>
  <span class="token literal-property property">watchContentBase</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token literal-property property">watchOptions</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 不监视的文件(支持正则)</span>
    <span class="token literal-property property">ignored</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">node_modules</span><span class="token regex-delimiter">/</span></span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token comment">// 启动gzip压缩</span>
  <span class="token literal-property property">compress</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token comment">// 端口号</span>
  <span class="token literal-property property">port</span><span class="token operator">:</span> <span class="token number">5000</span><span class="token punctuation">,</span>
  <span class="token comment">// 域名</span>
  <span class="token literal-property property">host</span><span class="token operator">:</span> <span class="token string">'localhost'</span><span class="token punctuation">,</span>
  <span class="token comment">// 自动打开浏览器</span>
  <span class="token literal-property property">open</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token comment">// 开启HMR功能</span>
  <span class="token literal-property property">hot</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token comment">// 不要显示启动服务器日志信息</span>
  <span class="token literal-property property">clientLogLevel</span><span class="token operator">:</span> <span class="token string">'none'</span><span class="token punctuation">,</span>
  <span class="token comment">// 除了一些基本启动信息以外，其他内容都不要显示</span>
  <span class="token literal-property property">quiet</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
  <span class="token comment">// 如果出错了，不要在控制台提示</span>
  <span class="token literal-property property">overlay</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
  <span class="token comment">// 服务器代理 --> 解决开发环境跨域问题</span>
  <span class="token literal-property property">proxy</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 一旦devServer(5000)服务器接受到 /api/xxx 的请求，就会把请求转发到另外一个服务器(3000)</span>
    <span class="token string-property property">'/api'</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
      <span class="token literal-property property">target</span><span class="token operator">:</span> <span class="token string">'http://localhost:3000'</span><span class="token punctuation">,</span>
      <span class="token comment">// 发送请求时，请求路径重写：将 /api/xxx --> /xxx （去掉/api）</span>
      <span class="token literal-property property">pathRewrite</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token string-property property">'^/api'</span><span class="token operator">:</span> <span class="token string">''</span>
      <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre>
<h3 id="optimization">optimization</h3>
<p>用于分割生成多JS文件</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">optimization</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">splitChunks</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">chunks</span><span class="token operator">:</span> <span class="token string">'all'</span>
    <span class="token comment">// 默认值，可以不写~</span>
    <span class="token comment">/* minSize: 30 * 1024, // 分割的chunk最小为30kb
    maxSiza: 0, // 最大没有限制
    minChunks: 1, // 要提取的chunk最少被引用1次
    maxAsyncRequests: 5, // 按需加载时并行加载的文件的最大数量
    maxInitialRequests: 3, // 入口js文件最大并行请求数量
    automaticNameDelimiter: '~', // 名称连接符
    name: true, // 可以使用命名规则
    cacheGroups: &#123;
      // 分割chunk的组
      // node_modules文件会被打包到 vendors 组的chunk中。--> vendors~xxx.js
      // 满足上面的公共规则，如：大小超过30kb，至少被引用一次。
      vendors: &#123;
        test: /[\\/]node_modules[\\/]/,
        // 优先级
        priority: -10
      &#125;,
      default: &#123;
        // 要提取的chunk最少被引用2次
        minChunks: 2,
        // 优先级
        priority: -20,
        // 如果当前要打包的模块，和之前已经被提取的模块是同一个，就会复用，而不是重新打包模块
        reuseExistingChunk: true
      &#125; 
    &#125;*/</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token comment">// 将当前模块的记录其他模块的hash单独打包为一个文件 runtime</span>
  <span class="token comment">// 解决：修改a文件导致b文件的contenthash变化</span>
  <span class="token literal-property property">runtimeChunk</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token function-variable function">name</span><span class="token operator">:</span> <span class="token parameter">entrypoint</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">runtime-</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>entrypoint<span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token template-punctuation string">`</span></span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token literal-property property">minimizer</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token comment">// 配置生产环境的压缩方案：js和css</span>
    <span class="token keyword">new</span> <span class="token class-name">TerserWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
      <span class="token comment">// 开启缓存</span>
      <span class="token literal-property property">cache</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token comment">// 开启多进程打包</span>
      <span class="token literal-property property">parallel</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token comment">// 启动source-map</span>
      <span class="token literal-property property">sourceMap</span><span class="token operator">:</span> <span class="token boolean">true</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
  <span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span></code></pre>
<h3 id="webpack5的变化">webpack5的变化</h3>
<h4 id="自动删除-node.js-polyfills">自动删除 Node.js Polyfills</h4>
<p>早期，webpack 的目标是允许在浏览器中运行大多数 node.js
模块，但是模块格局发生了变化，许多模块用途现在主要是为前端目的而编写的。webpack
&lt;= 4 附带了许多 node.js 核心模块的
polyfill，一旦模块使用任何核心模块（即 crypto
模块），这些模块就会自动应用。</p>
<p>尽管这使使用为 node.js 编写的模块变得容易，但它会将这些巨大的
polyfill 添加到包中。在许多情况下，这些 polyfill 是不必要的。</p>
<p>webpack 5 会自动停止填充这些核心模块，并专注于与前端兼容的模块。</p>
<p>迁移：</p>
<ul>
<li>尽可能尝试使用与前端兼容的模块。</li>
<li>可以为 node.js 核心模块手动添加一个
polyfill。错误消息将提示如何实现该目标。</li>
</ul>
<h4 id="chunk-和模块-id">Chunk 和模块 ID</h4>
<p>添加了用于长期缓存的新算法。在生产模式下默认情况下启用这些功能。</p>
<p><code>chunkIds: "deterministic", moduleIds: "deterministic"</code></p>
<h4 id="chunk-id">Chunk ID</h4>
<p>你可以不用使用
<code>import(/* webpackChunkName: "name" */ "module")</code>
在开发环境来为 chunk 命名，生产环境还是有必要的</p>
<p>webpack 内部有 chunk 命名规则，不再是以 id(0, 1, 2)命名了</p>
<h4 id="tree-shaking-1">Tree Shaking</h4>
<ol type="1">
<li>webpack 现在能够处理对嵌套模块的 tree shaking</li>
</ol>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">// inner.js</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">const</span> b <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>

<span class="token comment">// module.js</span>
<span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> inner <span class="token keyword">from</span> <span class="token string">'./inner'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token punctuation">&#123;</span> inner <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token comment">// user.js</span>
<span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> module <span class="token keyword">from</span> <span class="token string">'./module'</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>module<span class="token punctuation">.</span>inner<span class="token punctuation">.</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>在生产环境中, inner 模块暴露的 <code>b</code> 会被删除</p>
<ol start="2" type="1">
<li>webpack 现在能够多个模块之前的关系</li>
</ol>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">import</span> <span class="token punctuation">&#123;</span> something <span class="token punctuation">&#125;</span> <span class="token keyword">from</span> <span class="token string">'./something'</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">usingSomething</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> something<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> <span class="token function">usingSomething</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>当设置了<code>"sideEffects": false</code>时，一旦发现<code>test</code>方法没有使用，不但删除<code>test</code>，还会删除<code>"./something"</code></p>
<ol start="3" type="1">
<li>webpack 现在能处理对 Commonjs 的 tree shaking</li>
</ol>
<h4 id="output-1">Output</h4>
<p>webpack 4 默认只能输出 ES5 代码</p>
<p>webpack 5 开始新增一个属性 output.ecmaVersion, 可以生成 ES5 和 ES6 /
ES2015 代码.</p>
<p>如：<code>output.ecmaVersion: 2015</code></p>
<h4 id="splitchunk">SplitChunk</h4>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">// webpack4</span>
<span class="token literal-property property">minSize</span><span class="token operator">:</span> <span class="token number">30000</span><span class="token punctuation">;</span></code></pre>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">// webpack5</span>
<span class="token literal-property property">minSize</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">javascript</span><span class="token operator">:</span> <span class="token number">30000</span><span class="token punctuation">,</span>
  <span class="token literal-property property">style</span><span class="token operator">:</span> <span class="token number">50000</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span></code></pre>
<h4 id="caching">Caching</h4>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">// 配置缓存</span>
<span class="token literal-property property">cache</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">// 磁盘存储</span>
  <span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"filesystem"</span><span class="token punctuation">,</span>
  <span class="token literal-property property">buildDependencies</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 当配置修改时，缓存失效</span>
    <span class="token literal-property property">config</span><span class="token operator">:</span> <span class="token punctuation">[</span>__filename<span class="token punctuation">]</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>缓存将存储到 <code>node_modules/.cache/webpack</code></p>
<h4 id="监视输出文件">监视输出文件</h4>
<p>之前 webpack
总是在第一次构建时输出全部文件，但是监视重新构建时会只更新修改的文件。</p>
<p>此次更新在第一次构建时会找到输出文件看是否有变化，从而决定要不要输出全部文件。</p>
<h4 id="默认值">默认值</h4>
<ul>
<li><code>entry: "./src/index.js</code></li>
<li><code>output.path: path.resolve(__dirname, "dist")</code></li>
<li><code>output.filename: "[name].js"</code></li>
</ul>

    </div>

    
    
    
      


    <footer class="post-footer">
          <div class="reward-container">
  <div></div>
  <button>
    赞赏
  </button>
  <div class="post-reward">
      <div>
        <img src="/images/wechatpay.png" alt="Liu Kairui 微信">
        <span>微信</span>
      </div>
      <div>
        <img src="/images/alipay.png" alt="Liu Kairui 支付宝">
        <span>支付宝</span>
      </div>

  </div>
</div>

          

<div class="post-copyright">
<ul>
  <li class="post-copyright-author">
      <strong>本文作者： </strong>Liu Kairui
  </li>
  <li class="post-copyright-link">
      <strong>本文链接：</strong>
      <a href="http://liukairui.me/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/" title="前端构建工具Grunt&amp;Gulp&amp;webpack笔记">http://liukairui.me/article/前端构建工具Grunt+Gulp+webpack/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>

          <div class="post-tags">
              <a href="/tags/%E5%89%8D%E7%AB%AF/" rel="tag"><i class="fa fa-tag"></i> 前端</a>
              <a href="/tags/%E7%AC%94%E8%AE%B0/" rel="tag"><i class="fa fa-tag"></i> 笔记</a>
              <a href="/tags/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/" rel="tag"><i class="fa fa-tag"></i> 构建工具</a>
              <a href="/tags/Grunt/" rel="tag"><i class="fa fa-tag"></i> Grunt</a>
              <a href="/tags/Gulp/" rel="tag"><i class="fa fa-tag"></i> Gulp</a>
              <a href="/tags/webpack/" rel="tag"><i class="fa fa-tag"></i> webpack</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/article/JS%E5%BC%80%E5%8F%91%E4%B8%AD%E7%9A%84%E5%B0%8FTips/" rel="prev" title="JS开发中的小Tips">
                  <i class="fa fa-chevron-left"></i> JS开发中的小Tips
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/article/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%8E%9F%E7%90%86%E7%AC%94%E8%AE%B0/" rel="next" title="操作系统原理笔记">
                  操作系统原理笔记 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






    <div class="comments" id="valine-comments"></div>
</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 2019 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Liu Kairui</span>
</div>
<div class="busuanzi-count">
    <span class="post-meta-item" id="busuanzi_container_site_uv">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-item" id="busuanzi_container_site_pv">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>
  <div class="addthis_inline_share_toolbox">
    <script src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-6231eb6f709fc868" async="async"></script>
  </div><script
  async
  src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"
></script>

 
<script src="https://cdn.jsdelivr.net/npm/moment@2.22.2/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment-precise-range-plugin@1.3.0/moment-precise-range.min.js"></script>
<script>
  function timer() {
    var ages = moment.preciseDiff(moment(),moment(20201101,"YYYYMMDD"));
    ages = ages.replace(/years?/, "年");
    ages = ages.replace(/months?/, "月");
    ages = ages.replace(/days?/, "天");
    ages = ages.replace(/hours?/, "小时");
    ages = ages.replace(/minutes?/, "分");
    ages = ages.replace(/seconds?/, "秒");
    ages = ages.replace(/\d+/g, '<span class="daysCnt" style="color:#1890ff">$&</span>');
    div.innerHTML = `我已在此等候你 ${ages}`;
    div.className="workDays";
  }
  var div = document.createElement("div");
  //插入到copyright之后
  var copyright = document.querySelector(".copyright");
  document.querySelector(".footer-inner").insertBefore(div, copyright.nextSibling);
  timer();
  setInterval("timer()",1000)
</script>



    </div>
  </footer>

  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/@next-theme/pjax@0.5.0/pjax.min.js" integrity="sha256-3NkoLDrmHLTYj7csHIZSr0MHAFTXth7Ua/DDt4MRUAg=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js" integrity="sha256-yt2kYMy0w8AbtF89WXb2P1rfjcP/HTHLT7097U8Y5b8=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pangu/4.0.7/pangu.min.js"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  
<script src="https://cdn.jsdelivr.net/npm/hexo-generator-searchdb@1.4.0/dist/search.js" integrity="sha256-vXZMYLEqsROAXkEw93GGIvaB2ab+QW6w3+1ahD9nXXA=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>


  <script class="next-config" data-name="mermaid" type="application/json">{"enable":true,"theme":"forest","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.14.0/mermaid.min.js","integrity":"sha256-7wT34TI0pEBeEFoi4z+vhuSddGh6vUTMWdqJ2SDe2jg="}}</script>
  <script src="/js/third-party/tags/mermaid.js"></script>

  <script src="/js/third-party/fancybox.js"></script>

  <script src="/js/third-party/pace.js"></script>

  
  <script data-pjax async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>


  <script class="next-config" data-name="leancloud_visitors" type="application/json">{"enable":true,"app_id":"ABKlVtS4cyaWYEwunPyK3sXt-9Nh9j0Va","app_key":"xxGXdTTEGEVifs2TLB35844I","server_url":"https://abklvts4.lc-cn-e1-shared.com","security":false}</script>
  <script src="/js/third-party/statistics/lean-analytics.js"></script>


  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","mhchem":true,"js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.min.js"}}</script>
<script src="/js/third-party/math/mathjax.js"></script>


  <script src="https://cdnjs.cloudflare.com/ajax/libs/quicklink/2.2.0/quicklink.umd.js" integrity="sha256-4kQf9z5ntdQrzsBC3YSHnEz02Z9C1UeW/E9OgnvlzSY=" crossorigin="anonymous"></script>
  <script class="next-config" data-name="quicklink" type="application/json">{"enable":true,"home":false,"archive":false,"delay":true,"timeout":3000,"priority":true,"url":"http://liukairui.me/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/"}</script>
  <script src="/js/third-party/quicklink.js"></script>
<script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5.7/lib/darkmode-js.min.js"></script>

<script>
var options = {
  bottom: '64px',
  right: 'unset',
  left: '32px',
  time: '0.5s',
  mixColor: 'transparent',
  backgroundColor: 'transparent',
  buttonColorDark: '#100f2c',
  buttonColorLight: '#fff',
  saveInCookies: true,
  label: '🌓',
  autoMatchOsTheme: true
}
const darkmode = new Darkmode(options);
window.darkmode = darkmode;
darkmode.showWidget();
</script>


<script class="next-config" data-name="valine" type="application/json">{"enable":true,"appId":"ABKlVtS4cyaWYEwunPyK3sXt-9Nh9j0Va","appKey":"xxGXdTTEGEVifs2TLB35844I","serverURLs":"https://abklvts4.lc-cn-e1-shared.com","placeholder":"请开始你的表演","avatar":"identicon","meta":["nick","mail","link"],"pageSize":10,"lang":"zh-CN","visitor":false,"comment_count":true,"recordIP":true,"enableQQ":true,"requiredFields":[],"el":"#valine-comments","path":"/article/%E5%89%8D%E7%AB%AF%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7Grunt+Gulp+webpack/"}</script>
<script>
document.addEventListener('page:loaded', () => {
  NexT.utils.loadComments(CONFIG.valine.el)
    .then(() => NexT.utils.getScript(
      'https://cdn.jsdelivr.net/npm/valine@1.4.14/dist/Valine.min.js',
      { condition: window.Valine }
    ))
    .then(() => {
      new Valine(CONFIG.valine);
    });
});
</script>


  <script async src="/js/fireworks.js"></script>




  <script src="/js/activate-power-mode.min.js"></script>
  <script>
    POWERMODE.colorful = true;
    POWERMODE.shake = false;
    document.body.addEventListener('input', POWERMODE);
  </script>




  <script src="/js/wobblewindow.js"></script>
  <script>
    //只在桌面版网页启用特效 记得同步到header.njk
    if( window.innerWidth > 768  ){
      $(document).ready(function () {
        
          $('body>main>header').wobbleWindow({
            radius: 50,
            movementTop: false,
            movementLeft: false,
            movementRight: false,
            debug: false,
          });
        

        //
        //  $('body header>aside').wobbleWindow({
        //    radius: 50,
        //    movementLeft: false,
        //    movementTop: false,
        //    movementBottom: false,
        //    position: 'fixed',
        //    debug: false,
        //  });
        //

        
          $('body>footer').wobbleWindow({
            radius: 50,
            movementBottom: false,
            movementLeft: false,
            movementRight: false,
            debug: false,
          });
        
      });
    }
  </script>


 
<script>
  $(document).ready(function(){
    var beian = document.querySelector(".footer-inner > .beian > a");
    var cpr=document.querySelector(".footer-inner > .copyright");
    var cnz=document.querySelector(".workDays");//.parentNode;
    var bsz=document.querySelector(".busuanzi-count");
    if(cnz!=null&&bsz!=null)
      cnz.parentNode.insertBefore(bsz,cnz);
    if(bsz == null || bsz == undefined || document.querySelector("#busuanzi_value_site_pv").innerText=="" || document.querySelector("#busuanzi_value_site_uv").innerText == "")
      bsz.remove();
    checkIndex();
    if(beian){cpr.classList.add('split-line');cpr.appendChild(beian);}
  })
  $(document).on('pjax:complete',checkIndex);
</script>



<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"log":false,"model":{"jsonPath":"/live2dw/assets/hijiki.model.json"},"display":{"position":"right","width":150,"height":300},"mobile":{"show":false},"react":{"opacity":0.7}});</script></body>
</html>
